c# WaitHandle的WaitOne(int, bool)方法

c# WaitHandle的WaitOne(int, bool)方法

WaitHandle类用于线程的同步。WaitOne方法用于阻止当前线程,直到当前WaitHandle接收到信号。
WaitOne(int, bool)方法是其中的一个重载。
第一个参数很好理解,表示当前线程等待信号的超时时间,单位是ms。
第二个参数表示等待之前是否退出上下文的同步域,true表示退出,false表示不退出。
用微软自身的例子来解释,下面是例子:

using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;

[Synchronization(true)]
public class SyncingClass : ContextBoundObject
{
    private EventWaitHandle waitHandle;

    public SyncingClass()
    {
        waitHandle =
           new EventWaitHandle(false, EventResetMode.ManualReset);
    }

    public void Signal()
    {
        Console.WriteLine("Thread[{0:d4}]: Signalling...", Thread.CurrentThread.GetHashCode());
        waitHandle.Set();
    }

    public void DoWait(bool leaveContext)
    {
        bool signalled;

        waitHandle.Reset();
        Console.WriteLine("Thread[{0:d4}]: Waiting...", Thread.CurrentThread.GetHashCode());
        signalled = waitHandle.WaitOne(10000, leaveContext);
        if (signalled)
        {
            Console.WriteLine("Thread[{0:d4}]: Wait released!!!", Thread.CurrentThread.GetHashCode());
        }
        else
        {
            Console.WriteLine("Thread[{0:d4}]: Wait timeout!!!", Thread.CurrentThread.GetHashCode());
        }
    }
}

public class TestSyncDomainWait
{
    public static void Main()
    {
        SyncingClass syncClass = new SyncingClass();

        Thread runWaiter;

        Console.WriteLine("\nWait and signal INSIDE synchronization domain:\n");
        runWaiter = new Thread(RunWaitKeepContext);
        runWaiter.Start(syncClass);
        Thread.Sleep(1000);
        Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode());
        // This call to Signal will block until the timeout in DoWait expires.
        syncClass.Signal();
        runWaiter.Join();

        Console.WriteLine("\nWait and signal OUTSIDE synchronization domain:\n");
        runWaiter = new Thread(RunWaitLeaveContext);
        runWaiter.Start(syncClass);
        Thread.Sleep(1000);
        Console.WriteLine("Thread[{0:d4}]: Signal...", Thread.CurrentThread.GetHashCode());
        // This call to Signal is unblocked and will set the wait handle to
        // release the waiting thread.
        syncClass.Signal();
        runWaiter.Join();
    }

    public static void RunWaitKeepContext(object parm)
    {
        ((SyncingClass)parm).DoWait(false);
    }

    public static void RunWaitLeaveContext(object parm)
    {
        ((SyncingClass)parm).DoWait(true);
    }
}

// The output for the example program will be similar to the following:
//
// Wait and signal INSIDE synchronization domain:
//
// Thread[0004]: Waiting...
// Thread[0001]: Signal...
// Thread[0004]: Wait timeout!!!
// Thread[0001]: Signalling...
//
// Wait and signal OUTSIDE synchronization domain:
//
// Thread[0006]: Waiting...
// Thread[0001]: Signal...
// Thread[0001]: Signalling...
// Thread[0006]: Wait released!!!

代码第5行,[Synchronization(true)]表示类SyncingClass(继承自ContextBoundObject)是一个同步域上下文类。它表示如果我们创建了一个这个SyncingClass类的一个实例,那么每个时刻只能由一个线程访问这个类实例,否则就被阻塞,一直等到其他线程访问的释放。
WaitHandle.WaitOne的第二个参数如果是false,意味着调用这个WaitOne的线程会保持上下文不变,也就意味着不会释放SyncingClass实例的占用。代码运行到54行也就会被阻塞住。
而如果WaitOne的第二个参数时true,那么好比是SyncingClass开了个后门,可以在WaitOne之前释放对自己的占用,便于我们访问这个实例的其他方法不被阻塞,因此这个时候64行顺利发送信号。

发布了108 篇原创文章 · 获赞 126 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_16587307/article/details/104040338