繁体   English   中英

使用EventWaitHandle和Dispatcher.BeginInvoke进行计划

[英]Scheduling with EventWaitHandle with Dispatcher.BeginInvoke

下面的代码具有两个线程,每个线程将20的string str写入其相应的文本框。 完成后, Thread t00发出信号, Thread t00 Thread t01启动并将共享string stry更改为x Thread t00应将20 y写入文本框, Thread t01应将20 x写入另一个文本框。 相反, Thread t00最终写入19 y和1 x 但是,如果在设置Thread.Sleep()之前添加Thread.Sleep() ,可以解决我遇到的问题(我得到20 x和20 y ),但是为什么呢? EventWaitHandle循环结束后,才不应该设置,有或无Thread.Sleep()

public partial class MainWindow : Window
{
    public string str = "y";
    static EventWaitHandle _waitHandle = new AutoResetEvent(false);

    public MainWindow()
    {
        InitializeComponent();

        Thread t00 = new Thread(() =>
        {
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(200);
                Action action00 = () =>
                {
                    tb00.AppendText(str);
                };
                Dispatcher.BeginInvoke(action00);
            }
            Thread.Sleep(200);  // <-- why this fix the problem??
            _waitHandle.Set();
        });
        t00.Start();


        Thread t01 = new Thread(() =>
        {
            Action action00 = () =>
            {
                tb01.AppendText("Waiting...\n");
            };
            Dispatcher.BeginInvoke(action00);
            _waitHandle.WaitOne();

            str = "x";
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(200);
                Action action = () =>
                {
                    tb01.AppendText(str);
                };
                Dispatcher.BeginInvoke(action);
            }
        });
        t01.Start();
    }
}

在此处输入图片说明

因为您正在使用BeginInvoke BeginInvoke异步调用UI线程上的委托。 它将消息放入UI线程消息队列中并返回,因此它返回的事实并不意味着实际执行了操作。

因此,在大多数情况下,当您设置等待句柄并且另一个线程接收到tb00.AppendText(str);信号并将stry更改为x -仍然存在未调用的tb00.AppendText(str); UI线程队列中的委托。 最终调用它时str已经是x

Thread.Sleep对此进行了“修复”,因为它为挂起的委托留出了一些时间在UI线程上执行。 使用Invoke代替BeginInvoke还可以“修复”该问题,因为Invoke是同步的,并且仅在UI线程上实际执行了委托之后才返回。

想想BeginInvoke()将工作单元推入队列。 当从工作队列中弹出第20个action00并执行时, str='x'已经执行,因此当action00实际运行时,它将打印x

Thread.Sleep(200)在执行str='x'之前给第20个action00时间弹出并运行,因此它将打印y

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM