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

Tra*_*vis 5 c# dispatcher

我发现很少有关于如何正确使用Dispatcher类的信息.

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

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

Thread thread = new Thread(Dispatcher.Run);
thread.Start();
Run Code Online (Sandbox Code Playgroud)

并尝试以后使用它:

Dispatcher.FromThread(thread).Invoke(MyMethodDelegate);
Run Code Online (Sandbox Code Playgroud)

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

我为实现这一点而做的是使用一个信号来确保调度程序在继续在主线程上使用之前运行.

Tra*_*vis 2

这就是我最终所做的,我相信这是您需要做的才能正确使用调度程序。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

InitDispatcher返回后,可以使用

Dispatcher.FromThread(executionThread).Invoke
Run Code Online (Sandbox Code Playgroud)

或者

Dispatcher.FromThread(executionThread).BeginInvoke
Run Code Online (Sandbox Code Playgroud)

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