C#使用AutoResetEvent发出两个线程的信号

时间:2014-05-25 16:32:08

标签: c# multithreading autoresetevent waitone


我需要创建一个使用两个线程计数到10的程序 一个线程应该打印偶数,另一个应该打印奇数 这些线程应按顺序打印数字(1,2,3,4,5 ...)

我已经完成了这段代码,但似乎没有用......有什么想法吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        private static AutoResetEvent autoEvent;
        private static int num = 10;

        static void DoWork(object data)
        {
            var counter = (int)data;

            if (counter == 1)
            {
                autoEvent.WaitOne();
            }

            while (counter <= num)
            {
                Console.WriteLine(counter);
                counter += 2;
                autoEvent.Set();
                autoEvent.WaitOne();
            }
        }

        static void Main(string[] args)
        {
            autoEvent = new AutoResetEvent(false);

            var evenCounter = new Thread(DoWork);
            evenCounter.Start(0);

            var notEvenCounter = new Thread(DoWork);
            notEvenCounter.Start(1);

            Console.ReadLine();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

该代码autoEvent.WaitOne()可能无法阻止,因为AutoResetEvent已处于信号状态:

        autoEvent.Set();
        autoEvent.WaitOne();

因此该线程不会按照您的计划等待另一个线程 要解决该问题,您需要使用2 AutoResetEvent s。一个线程将在第一个AutoResetEvent上等待,第二个线程将在第二个AutoResetEvent上等待。每个帖子都会发出一个AutoResetEvent的信号,表示该属于&#39;到另一个线程 为了证明我的想法,我只会向您展示需要进行更改的代码行:

private static AutoResetEvent autoEvents[] = new AutoResetEvent[2];

...

autoEvents[0] = new AutoResetEvent(false);
autoEvents[1] = new AutoResetEvent(false);

...

var counter = (int)data;
int initial_counter = counter;

...

if (counter == 1)
{
autoEvents[initial_counter].WaitOne();
}

...

autoEvents[1 - initial_counter].Set();
autoEvents[initial_counter].WaitOne();

在DoWork结束时发出相应的AutoResetEvent以避免无限制阻塞另一个线程:

autoEvents[1 - initial_counter].Set();

答案 1 :(得分:0)

这似乎是你的问题:

   autoEvent.Set();
   autoEvent.WaitOne();

您可以设置锁定,然后立即等待锁定,这将导致任意执行模式。

我建议您使用2个锁,因此一个线程可以阻止另一个。

答案 2 :(得分:0)

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {

            Thread t1 = new Thread(Method1);
            Thread t2 = new Thread(Method2);
            t1.Start();
            Thread.Sleep(100);
            t2.Start();
            t1.Join();
            t2.Join();
            _autoEvent1.Close();
            _autoEvent2.Close();
        }

        private static void Method1()
        {

            do
            {
               _autoEvent2.WaitOne();

                if (!SharedCode(Thread.CurrentThread.ManagedThreadId))
                {
                    break;
                }

                _autoEvent1.Set();
            } while (true);
        }

        private static void Method2()
        {
            do
            {
                _autoEvent1.WaitOne();
                //_autoEvent2.Set();
                if (!SharedCode(Thread.CurrentThread.ManagedThreadId))
                    break;
                _autoEvent2.Set();
            } while (true);
        }

        private static bool SharedCode(int threadId)
        {
           lock (_lockObject)
            {

                Interlocked.Increment(ref _count);
                if (_count > 10)
                    return false;
                Console.WriteLine("ThreadId={0} , count={1}", threadId,_count);
            }

            return true;
        }
        private  static AutoResetEvent _autoEvent1 = new AutoResetEvent(true);
        private static AutoResetEvent _autoEvent2 = new AutoResetEvent(true);
        private static Object _lockObject = new object();
        private static int _count = 0;
    }
}