C#中的异步线程

1.通过委托,开启异步线程

  Action是委托类型,BeginInvoke 开启异步线程。正常情况下,Main线程是顺序执行的,但是开启异步线程后,程序的执行顺序由调度决定。执行结果可能先输出"Main",后输出"Method",也可能是相反顺序。

static void Method(string str)
{
    Console.WriteLine(str);
}
static void Main(string[] args)
{           
    Action<string> action = Method;
    //BeginInvoke 开启异步线程
    action.BeginInvoke("Method", null, null);
    Console.WriteLine("Main");          
}

2.获得异步线程的返回值

   想要获得异步线程的返回值,需要判断线程何时结束,判断异步线程结束的方法有:while循环,等待句柄,回调函数等。

2.1 while循环

   BeginInvoke的返回值是IAsyncResult,表示当前线程的状态。IsCompleted表示当前线程是否结束。当线程结束后,调用EndInvoke 获得线程的返回值。

   当函数执行时间比较长时,采用异步线程比较合适,比如下载,网络传输等。下面例子中计算整数的平方,不会花费太长时间,因此使用Thread.Sleep(10)使线程暂停10毫秒。

class Program
{
    static int Square(int num)
    {
        Thread.Sleep(10);
        return num * num;
    }
    static void Main(string[] args)
    {
        Func<int, int> func = Square;
        IAsyncResult async = func.BeginInvoke(10, null, null);  //IAsyncResult 表示当前线程的状态
        while (!async.IsCompleted)
        {
            Console.Write(".");
        }
        //EndInvoke 获得异步线程的返回值
        int result = func.EndInvoke(async);
        Console.WriteLine("result = " + result);

        Console.ReadKey();
    }
}

执行结果

2.2 等待句柄

   AsyncWaitHandle用于等待异步操作完成的WaitHandle,WaitOne阻止当前线程,直到WaitHandle收到信号,参数为设置的超时时间。如果该时间内线程结束,则返回ture,否则返回false。

class Program
{
    static int Square(int num)
    {
        Thread.Sleep(10);
        return num * num;
    }
    static void Main(string[] args)
    {
        Func<int, int> func = Square;
        IAsyncResult async = func.BeginInvoke(10, null, null);  
        bool flag = async.AsyncWaitHandle.WaitOne(1000);
        if (flag)
        {
            int result = func.EndInvoke(async);
            Console.WriteLine("result = " + result);
        }

        Console.ReadKey();
    }
}

2.3 回调函数

      BeginInvoke倒数第二个参数是一个委托,当线程结束时,就调用该委托指向的回调方法。最后一个参数给回调方法传递数据。

       OnCallBack是回调函数,线程结束时执行。func是传递给回调方法的参数。

class Program
{
    static int Square(int num)
    {
        Thread.Sleep(10);
        return num * num;
    }
    static void OnCallBack(IAsyncResult async)
    {
        Func<int, int> function = async.AsyncState as Func<int, int>;
        int result = function.EndInvoke(async);
        Console.WriteLine("在回调函数中取得结果:" + result);
    }

    static void Main(string[] args)
    {
        Func<int, int> func = Square;
        func.BeginInvoke(10, OnCallBack, func);

        Console.ReadKey();
    }
}

2.4 Lambda表达式

    Lambda表达式可以访问外部数据,所以func不再需要作为参数传递,BeginInvoke的最后一个参数设为null。

class Program
{
    static int Square(int num)
    {
        Thread.Sleep(10);
        return num * num;
    }
    static void Main(string[] args)
    {
        Func<int, int> func = Square;
        func.BeginInvoke(10, async =>
        {
            int result = func.EndInvoke(async);
            Console.WriteLine("在Lambda表达式取得结果:" + result);
        }, null);

        Console.ReadKey();
    }
}

猜你喜欢

转载自blog.csdn.net/liyazhen2011/article/details/81201862