从一个事件信号中释放许多线程

时间:2015-07-26 18:54:55

标签: c# multithreading

我有一个应用程序,其中多个线程必须等待事件以指示列表中的新数据可用。我的期望是我可以在每个线程中使用AutoResetEvent,WaitOne,然后在数据可用时设置事件。

但是,因为它是自动重置,所以第一个线程清除事件并且不释放其他线程。现在我可以把它作为一个手动重置并实现一个计数器,但我的感觉是这是一个常见的问题,因此必须有一个标准的方法来做到这一点,但搜索文档我找不到。< / p>

有任何帮助吗?以下是一些不会释放所有线程的示例代码:

    static AutoResetEvent eve = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        var threads = new List<Thread>();
        for (int i = 0; i < 10; ++i)
        {
            int iCopy = i;
            var t = new Thread(() => thread(iCopy));
            threads.Add(t);
            t.Start();
        }
        Console.WriteLine("Pausing");
        Thread.Sleep(5000);
        eve.Set();
        foreach (var t in threads) t.Join();
        Console.WriteLine("All done");
        Console.ReadKey();
    }

    static void thread(int n)
    {
        eve.WaitOne();
        Console.WriteLine("Thread {0}", n);
    }

3 个答案:

答案 0 :(得分:1)

只需使用ManualResetEvent代替AutoRestEvent。不需要反击。我试过,下面的代码就是代码。

    static ManualResetEvent eve = new ManualResetEvent(false);

    static void Main(string[] args)
    {
        var threads = new List<Thread>();
        for (int i = 0; i < 10; ++i)
        {
            int iCopy = i;
            var t = new Thread(() => thread(iCopy));
            threads.Add(t);
            t.Start();
        }
        Console.WriteLine("Pausing");
        Thread.Sleep(5000);
        eve.Set();
        foreach (var t in threads) t.Join();
        Console.WriteLine("All done");
        Console.ReadKey();
    }

    static void thread(int n)
    {
        eve.WaitOne();
        Console.WriteLine("Thread {0}", n);
    }

答案 1 :(得分:0)

  

我有一个应用程序,其中多个线程必须等待事件以指示列表中的新数据可用。我的期望是我可以在每个线程中使用AutoResetEvent,WaitOne,然后在数据可用时设置事件。

你有一点XY Problem,但幸好你包括了你的&#34; X&#34;是(一旦可用,让线程从列表中获取新数据)。

基于您的描述,我认为您最好使用BlockingCollection,您可以根据需要调整尽可能多的线程,只要数据可用,它们都会阻塞直到新数据可用他们取消阻止并获取数据,直到没有剩下的数据再重新阻止。

using System;
using System.Collections.Concurrent;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static BlockingCollection<int> _items = new BlockingCollection<int>(); 
        static void Main(string[] args)
        {
            //Start up 4 threads
            var threads = new Thread[4];
            for (int i = 0; i < threads.Length; i++)
            {
                var iCopy = i;
                threads[i] = new Thread(() => ProcessItems(iCopy));
                threads[i].IsBackground = true;
                threads[i].Start();
            }

            //Give the threads 5 items to process.
            for (int i = 0; i < 5; i++)
            {
                _items.Add(i);
            }

            Console.WriteLine("All items queued, sleeping 2 seconds");
            Thread.Sleep(2000);

            //Give the threads 10 more items to process.
            for (int i = 0; i < 10; i++)
            {
                _items.Add(i);
            }
            _items.CompleteAdding();
            Console.WriteLine("Marked adding complete");

            foreach (var t in threads) t.Join();

            Console.WriteLine("All threads complete");
            Console.ReadLine();
        }

        static void ProcessItems(int i)
        {
            var rnd = new Random(i);
            foreach (var item in _items.GetConsumingEnumerable())
            {
                Console.WriteLine("Thread {0} Processing item {1}", i, item);

                //Simulate a random amount work
                Thread.Sleep(rnd.Next(100, 500));
            }
        }
    }
}

答案 2 :(得分:0)

如果你真的只想释放所有等待的线程,请使用一个信号量数组,每个线程一个。当你想要它们全部去时,在一个循环中向每个信号量发送一个单元。