如何确保此多线程问题的确定性结果?

时间:2010-10-06 12:54:04

标签: c# multithreading

请考虑以下测试代码段:

        // act
        AutoResetEvent workDoneEvent = new AutoResetEvent(false);
        ThreadPool.QueueUserWorkItem(delegate
                                         {
                                             ProcessAndSignal(processor, workDoneEvent);
                                         }, null);

        // let worker thread have a go
        workDoneEvent.WaitOne();
        blockingFetcher.WaitForNextMessage = false;

        // assert
        Assert.That(processor.StopCause, Is.Null);
    }

    private static void ProcessAndSignal(MessageProcessor processor, AutoResetEvent workDoneEvent)
    {
        workDoneEvent.Set();
        // this invocation will block until the WaitForNextMessageFlag is set
        processor.ProcessMessages();
    }

理想情景:

  1. ProcessAndSignalMethod在线程池上排队但未开始执行。
  2. 主要线程阻止(autoResetEvent.WaitOne())
  3. 工作线程开始执行“ProcessAndSignal”方法
  4. 工作线程有足够的时间发信号并开始执行ProcessMessages方法
  5. 主线程重新生成并设置将导致ProcessAndSignal方法正常完成的属性
  6. 是否会出现以下情况?

    1)ProcessAndSignal()将在主线程将AutoResetEvent设置为WaitOne()之前开始执行,这将导致死锁(processor.ProcessMessages()将进入不定式循环)

1 个答案:

答案 0 :(得分:1)

是的,可能会出现这种情况。是的,如果你没有将bool变量声明为volatile,它就会死锁。只是不要使用bool,使用像你一样的事件。

逻辑看起来很奇怪,它闻起来就像你试图让主线程等待处理完成。 workDoneEvent实际上并不表示工作已完成。现在主线程将在工作完成之前检查断言,这可能不太好。如果意图是它表示工作者已完成,那么ProcessAndSignal应该是在方法结束时调用Set()的那个。主线程应该调用WaitOne()。

如果这完全准确,那么你就不应该使用QUWI,只需直接调用ProcessAndSignal而不使用线程。 更高效,线程问题零赔率。