asp.net中ManualResetEvent类使用方法

作者:袖梨 2022-06-25

ManualResetEvent详解

ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。一旦它被终止,ManualResetEvent 将保持终止状态(即对 WaitOne 的调用的线程将立即返回,并不阻塞),直到它被手动重置。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。

ManualResetEvent例子

假设有一个程序中调用了三个异步方法,代码如下:

 

 代码如下 复制代码

public class Test
{
    public void Todo(string message)
    {
        Console.WriteLine("{0} {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message);
    }

    private Action _todo = null;

    public Test()
    {
        _todo = Todo;
    }

    public IAsyncResult BeginTodo(string message, AsyncCallback callback, object state)
    {
        return _todo.BeginInvoke(message, callback, state);
    }

    public void EndTodo(IAsyncResult ar)
    {
        _todo.EndInvoke(ar);
    }
}

public class Program
{
    static void callback1(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
    }

    static void callback2(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
    }

    static void callback3(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
    }

    static public void Main(string[] args)
    {
        Test test1 = new Test();
        test1.BeginTodo("test1", callback1, test1);

        Test test2 = new Test();
        test2.BeginTodo("test2", callback2, test2);

        Test test3 = new Test();
        test3.BeginTodo("test3", callback3, test3);

        Console.ReadKey();
    }
}

执行结果如下图所示:

asp.net中ManualResetEvent类使用方法

也就是说,异步方法的执行顺序是不固定的,但有时我们希望它们能按顺序执行,修改代码如下:

 

 代码如下 复制代码

public class Program
{
    static void callback1(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);

        Test test2 = new Test();
        test2.BeginTodo("test2", callback2, test2);
    }

    static void callback2(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);

        Test test3 = new Test();
        test3.BeginTodo("test3", callback3, test3);
    }

    static void callback3(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
    }

    static public void Main(string[] args)
    {
        Test test1 = new Test();
        test1.BeginTodo("test1", callback1, test1);        

        Console.ReadKey();
    }
}

看着有没有感觉很乱?能不能让代码既像开始那样有条理,又能按顺序执行呢?ManualResetEvent类出场了:

 

 代码如下 复制代码

public class Program
{
    static ManualResetEvent done1 = new ManualResetEvent(false);
    static ManualResetEvent done2 = new ManualResetEvent(false);
    static ManualResetEvent done3 = new ManualResetEvent(false);

    static void callback1(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
        done1.Set();
    }

    static void callback2(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
        done2.Set();
    }

    static void callback3(IAsyncResult ar)
    {
        Test test = (Test)ar.AsyncState;
        test.EndTodo(ar);
        done3.Set();
    }

    static public void Main(string[] args)
    {
        Test test1 = new Test();
        test1.BeginTodo("test1", callback1, test1);
        done1.WaitOne(); //阻塞当前线程,待Set后继续执行

        Test test2 = new Test();
        test2.BeginTodo("test2", callback2, test2);
        done2.WaitOne(); //阻塞当前线程,待Set后继续执行

        Test test3 = new Test();
        test3.BeginTodo("test3", callback3, test3);
        done3.WaitOne(); //阻塞当前线程,待Set后继续执行

        Console.ReadKey();
    }
}

相关文章

精彩推荐