如何在C#线程中使用等待句柄?

时间:2011-04-04 13:07:39

标签: c# multithreading

我的程序中有三个线程,我希望当线程1完成时它会发出线程2的信号以启动,当线程2完成时它应该通知线程3开始。

我怎样才能实现这一目标,我知道在C#中有等待句柄,但我不知道如何使用它们?

以下是我的程序代码:

class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(Task1);
            Thread t2 = new Thread(Task2);
            Thread t3 = new Thread(Task3);

            t1.Start();
            t2.Start();
            t3.Start();

            Console.Read();
        }

        public static void Task1()
        {
            Console.WriteLine("I am assigned task 1:");
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine("Task1" );
            }
        }
        public static void Task2()
        {
            Console.WriteLine("I am assigned task 2:");
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine("Task2");
            }
        }
        public static void Task3()
        {
            Console.WriteLine("I am assigned task 3:");
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine("Task3");
            }
        }
    }

6 个答案:

答案 0 :(得分:6)

您需要将事件传递给线程函数,这些函数指示每个事件完成时要发出什么信号以及在运行之前要等待的内容。看看下面的(未经测试的)代码,看看我的意思:

class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(Task1);
            ManualResetEvent e1=new ManualResetEvent(false);

            Thread t2 = new Thread(Task2);
            ManualResetEvent e2=new ManualResetEvent(false);

            Thread t3 = new Thread(Task3);
            ManualResetEvent e3=new ManualResetEvent(false);

            t1.Start(()=>Task1(e1));
            t2.Start(()=>Task2(e1,e2));
            t3.Start(()=>Task3(e2,e3);

            Console.Read();

            t1.Join();
            t2.Join();
            t3.Join();
        }

        public static void Task1(EventWaitHandle handle)
        {
            Console.WriteLine("I am assigned task 1:");
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine("Task1" );
            }
            handle.Set();

        }
        public static void Task2(EventWaitHandle waitFor, EventWaitHandle handle)
        {
            waitFor.WaitOne();

            Console.WriteLine("I am assigned task 2:");
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine("Task2");
            }

            handle.Set();
        }
        public static void Task3(EventWaitHandle waitFor, EventWaitHandle handle)
        {
            waitFor.WaitOne();

            Console.WriteLine("I am assigned task 3:");
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine("Task3");
            }

            handle.Set();
        }
    }

答案 1 :(得分:4)

您似乎希望运行任务1 - 3以执行同步。所以,你不妨这样做:

Task1();
Task2();
Task3();

如果要将这些任务的执行卸载到另一个线程,可以执行以下操作:

static void RunTasks()
{
    Task1();
    Task2();
    Task3();
}

static void Main()
{
   new Thread(RunTasks).Start();
}

如果您确实希望每个任务在单独的线程上运行,并等待上一个任务完成,则可以使用Thread.Join方法。

修改

由于您确实想使用等待句柄来完成此任务,请查看ManualResetEvent类。

  

通知一个或多个等待线程   事件已经发生。

在其上调用WaitOne方法等待事件,并使用Set方法发出信号。

示例(可怕的人为代码):

var afterT1Event = new ManualResetEvent(false);
var afterT2Event = new ManualResetEvent(false);

Thread t1 = new Thread(() => { Task1(); afterT1Event.Set(); });
Thread t2 = new Thread(() => { afterT1Event.WaitOne(); Task2(); afterT2Event.Set(); });
Thread t3 = new Thread(() => { afterT2Event.WaitOne(); Task3(); });

t1.Start();
t2.Start();
t3.Start();

答案 2 :(得分:2)

如果您想使用WaitHandles来实现这些目标,那么您可以执行以下操作:

声明以下两个字段:

static ManualResetEvent handle1 = new ManualResetEvent(false);
static ManualResetEvent handle2 = new ManualResetEvent(false);

然后在Task1的末尾添加:

    handle1.Set();

在Task2的开头,添加:

    handle1.WaitOne();

然后在最后添加

    handle2.Set();

然后最后在Task3的开头添加

    handle2.WaitOne();

答案 3 :(得分:0)

这感觉非常人为,几乎像家庭作业......

...但基本上你可以在线程上使用Join来等待它。

或者旧的msdn教程/示例非常合理:http://msdn.microsoft.com/en-us/library/aa645740(VS.71).aspx

答案 4 :(得分:0)

您可以使用ManualResetEvents和WaitHandle.WaitAny。基本上,当一个线程完成时,您将使用ManualResetEvent(ManualResetEvent.Set())通知另一个线程。

ManualResetEvent threadFinished = new ManualResetEvent(false);

//You would set this in the thread that has finished
threadFinished.Set()

//You would use this in the thread that you want to wait for this event to be signalled
int nWait = WaitHandle.WaitAny(new ManualResetEvent[] { threadFinished }, 10, true);

//if yes stop thread
if (nWait == 0)
{
    //Thread is finished
}

答案 5 :(得分:0)

我认为使用thread.join()将更简单的任何其他解决方案