C#中的異步編程:await和async

根據代碼示例來學習,編程

  1. 建立一個函數來模擬時間消耗的方法,此處爲GetSomeThing函數。併發

  2. 要使用異步編程,須要使用一個async修飾的方法來包裝調用GetSomeThing函數,此函數的返回值爲Task類型,該類型表示進行並行運算的任務引用。此處示例爲ConsumeManyTime函數。dom

  3. 如今就能夠直接使用異步方式了,參考TestOne()函數中的代碼,其實就是直接調用第二步中的函數ConsumeManyTime();

總結:
異步編程雖然示例三步,可是實際上就是兩步的事情,第一步是模擬應用,跟異步編程自己沒有關係,第二步包裝一個Task返回類型的async修飾的方法,該方法實際調用應用函數,第三步調用第二步的方法,從而執行對模擬應用的異步執行。異步

附加:
除了異步編程之外,C#還提供了併發編程相關功能,極大簡化了併發任務的開發,能夠讓開發人員無需建立線程池以及管理線程這些工做,就能夠直接使用併發開發帶來的優點。 示例代碼見Testpallral()async

代碼以下ide

class Program
    {

        static int i = 0;
        //模擬耗時的運算或者IO
        public static bool GetSomeThing(string a)
        {
            Thread.Sleep((new Random()).Next()%10*1000);
            i++;
            Console.WriteLine(DateTime.Now.ToLongTimeString()+"5-" + Thread.GetCurrentProcessorId().ToString());
            return true;
        }
        //生成一個task類型,其中包裝調用GetSomeThing
        public static Task<bool> GetSomeThingAsync(string a)
        {
            return Task.Run<bool>(()=> { return GetSomeThing(a); }
            );
        }
//方式1:包裝給調用方使用的方法,使用async修飾,由於裏面有await。 調用方執行到await會當即返回,後續的內容再也不直接調用, await以後的方法都會在可能在其餘線程中使用,
    public async static void ConsumeManyTime()
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "3-" +Thread.GetCurrentProcessorId().ToString());
        bool result = await GetSomeThingAsync("test");
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "4-" +Thread.GetCurrentProcessorId().ToString());
    }
    //方式2:這種調用方式是在異步執行完畢後,能夠繼續執行預約的後續函數,能夠理解爲一種回調機制。
    public static void ContinueTaskWithConsumeManyTime()
    {
        Task<bool> t1 = GetSomeThingAsync("test");
        t1.ContinueWith(t => { Console.WriteLine("after await finished " + t.Result + " " + Thread.GetCurrentProcessorId().ToString() + " " + i.ToString()); });
    }
    //方式3:多任務等待方式
    public static async void TaskWhenConsumeManyTime()
    {
        Task<bool> t1 = GetSomeThingAsync("test");
        Task<bool> t2 = GetSomeThingAsync("test");
        await Task.WhenAll(t1, t2);
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "6-" + Thread.GetCurrentProcessorId().ToString());

    }

    //async 和await的基本使用
    public static void TestOne()
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString());
        ConsumeManyTime();
        ConsumeManyTime();
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString());
        Console.WriteLine("繼續輸入");
        while (Console.ReadLine() != "stop")
        {
            Console.WriteLine("繼續輸入");
        }
    }

    public static void TestWithContinue()
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString());
        ContinueTaskWithConsumeManyTime();
        ContinueTaskWithConsumeManyTime();
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString());
        Console.WriteLine("繼續輸入");
        while (Console.ReadLine() != "stop")
        {
            Console.WriteLine("繼續輸入");
        }
    }

    public static void TestWhen()
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString());
        TaskWhenConsumeManyTime();

        Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString());
        Console.WriteLine("繼續輸入");
        while (Console.ReadLine() != "stop")
        {
            Console.WriteLine("繼續輸入");
        }
    }

    public static  void Testpallral()
    {
        ParallelLoopResult result =

              Parallel.For(0, 100, async (int i) =>

              {

                  Console.WriteLine(DateTime.Now.ToLongTimeString() + "{0}, task: {1}, thread: {2}", i,

                  Task.CurrentId, Thread.CurrentThread.ManagedThreadId);

                  await Task.Delay(10);
                  Console.WriteLine(DateTime.Now.ToLongTimeString() + "after delay");

              });

        while (Console.ReadLine() != "stop")
        {
            Console.WriteLine("繼續輸入");
        }
    }

    public static void Testpallral2()
    {
        ParallelLoopResult result =
              Parallel.For(0, 100,async(int i, ParallelLoopState pls) =>
              {
                  Console.WriteLine(DateTime.Now.ToLongTimeString() + "{0}, task: {1}, thread: {2}", i,
                  Task.CurrentId, Thread.CurrentThread.ManagedThreadId);

                  await Task.Delay(10);
                    if (i > 5) pls.Break();
            Console.WriteLine(DateTime.Now.ToLongTimeString() + "after delay");

              }
        );

        while (Console.ReadLine() != "stop")
        {
            Console.WriteLine("繼續輸入");
        }
    }
    static void Main(string[] args)
    {
        //TestWhen();
        //Testpallral2();

    }

}
相關文章
相關標籤/搜索