木子屋 Dnawo's BLOG

ManualResetEvent类用法小结

👤 dnawo 📅 2014-08-18 👁 4443 👍 0 💬 0 🔄 本站原创
假设有一个程序中调用了三个异步方法,代码如下:

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

    private Action<string> _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();
    }
}

执行结果如下图所示:

图片

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

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();
    }
}

评论(0)

暂无评论。

计算题
评论需审核通过后显示
← 上一篇 BeginInvoke和EndInvoke方法学习小结 下一篇 → Http 请求头中的 Proxy-Connection[转]