[英]Thread Safe Alternative to Thread.Sleep that allows browser activity in c#
我需要一个简单的等待函数,该函数允许处理浏览器事件并且是线程安全的。 一位同事说,在使用多个线程时切勿使用DoEvents。
我注意到当我使用Thread.Sleep(10000);
我的浏览器活动暂停,直到睡眠完成。
谁能推荐一个替代方案?
下面是一些代码:
public static int f_sleep(int time)
{
System.DateTime now = System.DateTime.Now;
System.TimeSpan duration = new System.TimeSpan(0, 0, 0, time);
System.DateTime then = now.Add(duration);
Thread this_thread = Thread.CurrentThread;
while (then > DateTime.Now)
{
//MessageBox.Show("NewTime:" + then + "Now:" + DateTime.Now);
//we do not want to use this because it's said to mess up multithreading
Application.DoEvents();
//Thread.CurrentThread.Sleep(10);
Thread.Sleep(10);
}
return 1;
}
private void f_run_selected_campaigns(object sender, EventArgs e)
{
jobs_datagrid.EndEdit();
int count_active = 0;
foreach (DataGridViewRow row in jobs_datagrid.Rows)
{
//MessageBox.Show(row.Cells[1].Value.ToString());
if (row.Cells[1].Value.ToString() == "True")
{
count_active++;
//troubleshooting
Thread this_thread = new Thread(() =>
this.Invoke((MethodInvoker)delegate
{
test("hello");
}
));
//threading properties
this_thread.Name = "thread_" + row.Cells[0].Value.ToString();
this_thread.IsBackground = true;
this_thread.Start();
}
}
if (count_active == 0)
{
MessageBox.Show("No campaigns are selected!");
}
}
private void test(string this_string)
{
MessageBox.Show(this_string);
//Thread.Sleep(1000);
f_sleep(10); //for some reason Thread.Sleep does not work well with my browser loading waiting so I drew this up to create a temp pause in the code logic, but it's causing my threads to not run asychronously
MessageBox.Show("Thread Done");
}
我仍然无法找到解决方案。 我认为会有一种简单的方法可以在允许UI元素和Web浏览器处理的同时暂停逻辑流程。
现在,我正在使用这两个来满足我的处理需求,当我使用多线程时,是否会再次咬住我……我不知道。
private int WaitBrowserLoading(Control browser)
{
lock(_locker)
{
tabcontrol_browser.Invoke((MethodInvoker) delegate {
for (int i = 0; i < 1000000; i++)
{
if(((WebBrowser)browser).ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
Thread.Sleep(10);
}else
{
break;
}
}
});
return 1;
}
}
public static int f_sleep(int time)
{
System.DateTime now = System.DateTime.Now;
System.TimeSpan duration = new System.TimeSpan(0, 0, 0, time);
System.DateTime then = now.Add(duration);
while (then > DateTime.Now)
{
Application.DoEvents();
Thread.Sleep(10);
}
return 1;
}
永远不要使用Thread.Sleep()等待其他事情完成。
如果您的应用正在等待浏览器控件完成页面或URL的加载,则应在浏览器控件上挂起一个事件,以便它在完成加载时告诉您。 您尚未说出正在使用的浏览器控件,而是寻找一个名为“ Loaded”或“ PageLoaded”或“ AfterNavigation”之类的事件。
如果您的代码中包含一系列步骤,而让浏览器加载特定的URL位于这些步骤的中间,则应将其余步骤移至浏览器控件的页面加载事件处理程序中,以便它们在页面之后执行已加载。
我不确定您要寻找的是什么,但是也许是:
System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
public Form1()
{
myTimer.Interval = 1000;
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Start();
//Do stuff.
}
void myTimer_Tick(object sender, EventArgs e)
{
myTimer.Stop();
//Do stuff when it ticks.
}
如果您可以控制浏览器控件提供的内容,那么可能会发生的一件事情是延迟的重定向。 为用户提供一个页面,该页面包含无限循环的gif动画进度指示器,并包含以下内容:
<META HTTP-EQUIV="refresh" CONTENT="5;URL=my-next-page">
该页面将显示进度指示器,并在5秒钟后将重定向到“ my-next-page”。
这会有所帮助吗? 它仅阻止您的新线程。
new Thread(() =>
{
Thread.Sleep(10000);
// do stuff
}).Start();
// and we're back, immediately
您也可以使用Task
,但要确保正在等待的任务不会阻止其他任务。 我的示例是强制使用新品牌线的“大锤方式”。
最后,如果其他所有方法均失败,则在调用DoEvents()时循环可能是一个选项。 您将需要阅读为什么此方法不好,以及应该如何避免它的坏处。 具体来说,当代码在循环中处理DoEvents()时,您应该积极禁止用户输入(读取和丢弃鼠标和键盘事件),否则应用程序的用户将能够与您的应用程序进行交互以调用菜单命令等。 ,但您的应用程序在等待时将不会处理这些命令。 但是,在完成DoEvents()循环后,它将立即处理所有命令。 您还可能需要担心其他事件(如果不这样做,则应用程序会显得笨拙),例如即将发生的系统关闭的全局通知等。
如果在UI线程上执行Thread.Sleep,则浏览器将无法执行任何操作,因为UI线程只是在休眠。 我认为那是你的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.