繁体   English   中英

使用 Dispatcher.Run() 时如何避免竞争条件?

[英]How do I avoid a race condition when using Dispatcher.Run()?

我几乎没有找到关于如何正确使用 Dispatcher class 的信息。

目前我正在使用它类似于这个问题,但有一个固有的竞争条件,我在任何地方都没有看到。

假设您使用以下代码启动调度程序线程:

Thread thread = new Thread(Dispatcher.Run);
thread.Start();

并尝试稍后使用它:

Dispatcher.FromThread(thread).Invoke(MyMethodDelegate);

这通常会引发 NullReferenceException,因为 Dispatcher.FromThread 调用可能会返回 null,因为无法保证 Dispatcher.Run 已被调用。

为了正确实现这一点,我所做的是使用信号来确保调度程序正在运行,然后再继续在主线程上使用它。

这是一个较短的版本,作为实用程序 function 完成,受的启发,所以我省略了评论。

private static Thread CreateDispatcherThread()
{
    using (var startedEvent = new ManualResetEventSlim()) 
    {
        var dispatcherThread = new Thread( _ => { 
            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(startedEvent.Set));
            Dispatcher.Run(); } );
        dispatcherThread.Start();
        startedEvent.WaitHandle.WaitOne();
        return dispatcherThread;
    }
}   

这就是我最终要做的事情,我相信您需要这样做才能正确使用 Dispatcher。

private Thread executionThread;
private object SyncObject {get;set;}
private delegate void DispatcherMethod();

private void InitDispatcher()
{
    this.SyncObject = new object();

    // Set up the dispatcher pump.  See Dispatcher.Run on MSDN.
    this.executionThread = new Thread(StartDispatcher);

    lock (this.SyncObject)
    {
        this.executionThread.Start();
        Monitor.Wait(this.SyncObject);
    }
}   


private void StartDispatcher()
{
    DispatcherMethod method = DispatcherStarted;
    // Enqueue a started event by adding an initial method on the message pump.
    // Use BeginInvoke because the dispatcher is not actually running yet.
    // The call to Dispatcher.CurrentDispatcher handles creating the actual
    // Dispatcher instance for the thread (see MSDN - Dispatcher.FromThread
    // does not initialize the Dispatcher).
    Dispatcher.CurrentDispatcher.BeginInvoke(method);
    Dispatcher.Run();
}


private void DispatcherStarted()
{
    lock (this.SyncObject)
    {
        Monitor.Pulse(this.SyncObject);
    }
}

InitDispatcher 返回后,可以使用

Dispatcher.FromThread(executionThread).Invoke

或者

Dispatcher.FromThread(executionThread).BeginInvoke

编组对调度程序线程的调用。

暂无
暂无

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

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