Thread Safe 替代 Thread.Sleep,允许 C# 中的浏览器活动

本文关键字:Thread 浏览器 活动 允许 Safe 替代 Sleep | 更新日期: 2023-09-27 18:16:40

我需要一个简单的等待函数,它允许浏览器事件处理并且是线程安全的。一位同事说,在使用多个线程时,永远不要使用 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 Safe 替代 Thread.Sleep,允许 C# 中的浏览器活动

永远不要使用 Thread.Sleep(( 来等待其他事情完成。

如果你的应用正在等待浏览器控件完成页面或 URL 的加载,则应在浏览器控件上挂钩一个事件,以便它在完成加载时告诉你。您还没有说明您正在使用的浏览器控件,但请查找名为"已加载"或"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.
}

这会有帮助吗?它只会阻止您的新线程。

new Thread(() =>
{
    Thread.Sleep(10000);
    // do stuff
}).Start();
// and we're back, immediately

您也可以使用 Task ,但请确保等待的那个不会阻止其他任务。我的样本是迫使新品牌线启动的"大锤方式"。

如果你在 UI 线程上执行 Thread.Sleep,则浏览器无法执行任何操作,因为 UI 线程只是处于睡眠状态。我认为这是你的问题。

如果您可以控制浏览器控件提供的内容,则可能有效的一件事是延时重定向。为用户提供一个页面,其中包含一个无休止循环的动画 gif 进度指示器,并包含以下内容:

<META HTTP-EQUIV="refresh" CONTENT="5;URL=my-next-page">

此页面将显示进度指示器,5 秒后它将重定向到"我的下一页"。

最后,如果所有其他方法都失败了,则在调用 DoEvents(( 时循环可能是一种选择。您需要阅读为什么此方法不好,以及您应该采取哪些措施来避免其不良。具体来说,当您的代码在循环处理 DoEvents(( 中时,您应该主动抑制用户输入(读取和丢弃鼠标和键盘事件(,否则应用程序的用户将能够与您的应用程序交互以调用菜单命令等,但您的应用程序在等待时不会处理这些命令。但是,它将在您完成 DoEvents(( 循环后立即立即处理所有命令。您可能还需要担心其他事件(或者如果您不担心,那么您的应用程序将显得笨拙(,例如即将关闭系统关闭的全局通知等。