发生事件时唤醒线程

nan*_*nan 6 c# events multithreading

我想在两个线程之间实现以下通信:

线程Alpha执行某些操作,然后暂停.接下来第二个线程(Beta)引发并恢复Alpha线程的事件.这个循环继续......

我做了类似下面的事情,但我不确定它是否是一个合适的设计.我也注意到Thread.Suspend()并且Thread.Resume()已被弃用.我期待听到有关此实现的任何建议以及更换弃用方法的首选方法.

namespace ThreadTester
{
    delegate void ActionHandler();

    class Alpha
    {
        internal Thread alphaThread;
        internal void Start()
        {
            while (true)
            {
                this.alphaThread.Suspend();
                Console.WriteLine("Alpha");
            }
        }
        internal void Resume()
        {
            while (this.alphaThread.ThreadState == ThreadState.Suspended)
            this.alphaThread.Resume();
        }
    }

    class Beta
    {
        internal event ActionHandler OnEvent;
        internal void Start()
        {
            for (int i = 0; i < 15; i++)
            {
                OnEvent();
                Thread.Sleep(1000);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Alpha alpha = new Alpha();
            alpha.alphaThread = new Thread(new ThreadStart(alpha.Start));
            alpha.alphaThread.Start();
            while (!alpha.alphaThread.IsAlive) ;

            Beta beta = new Beta();
            beta.OnEvent += new ActionHandler(alpha.Resume);
            Thread betaThread = new Thread(new ThreadStart(beta.Start));
            betaThread.Start();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jor*_*ren 12

这是您通常使用等待句柄的地方,特别是事件等待句柄.

如果WaitOne在等待句柄上调用该方法,它将阻塞您的线程,直到某个其他线程调用Set同一个等待句柄.

事件等待句柄有两个重要的简单类型:AutoResetEvent将在线程通过后自动重置WaitOne.只有在调用时,ManualResetEvent才会自动重置Reset.


Dan*_*ant 10

这是一个常见的同步问题,有几种方法(如果你不是非常小心的话,所有这些方法都很容易搞砸):

  1. 等待处理(Joren已经描述了这些).

  2. Monitor.WaitMonitor.Pulse.这里有一个问题是Pulse只会唤醒已经处于Wait状态的线程,所以你必须小心如何管理同步对象的锁定.

  3. 使用.NET 4中的新TPL(也可以反向移植到.NET 3.5),您可以设置异步任务并根据以前完成的任务定义任务继续的条件.理解如何构建代码以利用任务和延续有一点学习曲线,但它比通过简单使用低级同步结构的非常艰难的道路要好得多(从长远来看). .这也为您提供了一个很好的前进道路,可以为您的逻辑添加更强大的错误处理和取消支持,因为协调这些内容的细节已经融入到TPL中.


Bri*_*eon 7

您的代码具有生产者 - 消费者模式的"感觉",但以错误的方式实现.你肯定不希望使用Thread.Suspend,并Thread.Resume以这种方式(或实际的任何方式).通过BlockingCollection类实现规范的生产者 - 消费者模式,实际上很容易获得您想要的排序和信号.

public class ProducerConsumer
{
    private BlockingCollection<object> m_Queue = new BlockingCollection<object>();

    public ProducerConsumer()
    {
        new Thread(Producer).Start();
        new Thread(Consumer).Start();
    }

    private void Consumer()
    {
        while (true)
        {
            object item = m_Queue.Take(); // blocks when the queue is empty
            Console.WriteLine("Consumer");
        }
    }

    private void Producer()
    {
        while (true)
        {
            m_Queue.Add(new object());
            Thread.Sleep(1000);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中Consumer,Producer将分别相当于你alphaThreadbetaThread.


Ste*_*end 2

通常,线程用于允许并行处理 > 1 项工作。我很好奇为什么你的设计要求线程 A 休眠,而线程 B 做某事,然后醒来并继续工作。为什么不让线程 A 自己完成这项工作呢?

您可能会受益于使用 .Net 4 的任务并行库- 然后线程 A 可以启动一个异步任务,该任务在单独的线程上自动执行,并且结果可供线程 A 使用,而无需显式的线程间信号传递(这可能会导致如果线程 A 或 B 发生故障,则在挂起的应用程序中)。