c#異步編程一


1.什么是異步

程序啟動時,系統會在內存中創建一個新的進程,進程是構成運行程序的資源合集,

在進程內部,系統創建了一個稱為線程的內核對象,它代表了真正執行的程序,

關於線程:

默認情況下,一個進程只包含一個線程,從程序開始一直執行到結束,

線程可以派生其他線程,因此在任意時刻,一個進程都可能包含不同狀態的多個線程,來執行程序的不同部分,

系統為處理器執行所規划的單元是線程,不是進程,

不使用異步示例:

 class MyDownload
    {
        Stopwatch sw = new Stopwatch();

        public void DoRun()
        {
            const int LargeNumber = 6000000;

            sw.Start();

            int t1 = CountCharacters(1, "http://www.miscrosoft.com");
            int t2 = CountCharacters(2, "http://www.illustratedcsharp.com");

            CountToALargeNumber(1, LargeNumber);
            CountToALargeNumber(2, LargeNumber);
            CountToALargeNumber(3, LargeNumber);
            CountToALargeNumber(4, LargeNumber);

            Console.WriteLine("Chars in http://www.miscrosoft.com  {0}", t1);
            Console.WriteLine("Chars in http://www.illustratedcsharp.com {0}", t2);
        }

        private int CountCharacters(int id, string uristring)
        {
            WebClient wc1 = new WebClient();
            Console.WriteLine("Starting call {0}  :  {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds);
            string result = wc1.DownloadString(new Uri(uristring));
            Console.WriteLine("  Call {0} completed  :  {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds);
            return result.Length;
        }

        public void CountToALargeNumber(int id, int value)
        {
            for (long i = 0; i < value; i++) ;
            Console.WriteLine("  End counting {0}  :  {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds);
        }

    }
 class Program
    {
        static void Main(string[] args)
        {
            MyDownload md = new MyDownload();
            md.DoRun();
            Console.ReadKey();
        }
    }

如果我們能初始化兩個CountCharacter調用,無需等待結果,而是直接執行4個CountToALargeNumber調用,然后在兩個CountCharacter方法調用結束后在獲取結果,就可以顯著的提升性能,即async/await,

class MyDownload
    {
        Stopwatch sw = new Stopwatch();

        public void DoRun()
        {
            const int LargeNumber = 6000000;

            sw.Start();

            Task<int> t1 = CountCharactersAsync(1, "http://www.miscrosoft.com");
            Task<int> t2 = CountCharactersAsync(2, "http://www.illustratedcsharp.com");

            CountToALargeNumber(1, LargeNumber);
            CountToALargeNumber(2, LargeNumber);
            CountToALargeNumber(3, LargeNumber);
            CountToALargeNumber(4, LargeNumber);

            Console.WriteLine("Chars in http://www.miscrosoft.com  {0}", t1.Result);
            Console.WriteLine("Chars in http://www.illustratedcsharp.com {0}", t2.Result);
        }

        private async Task<int> CountCharactersAsync(int id, string uristring)
        {
            WebClient wc1 = new WebClient();
            Console.WriteLine("Starting call {0}  :  {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds);
            string result = await wc1.DownloadStringTaskAsync(new Uri(uristring));
            Console.WriteLine("  Call {0} completed  :  {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds);
            return result.Length;
        }

        public void CountToALargeNumber(int id, int value)
        {
            for (long i = 0; i < value; i++) ;
            Console.WriteLine("  End counting {0}  :  {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds);
        }

    }
 class Program
    {
        static void Main(string[] args)
        {
            MyDownload md = new MyDownload();
            md.DoRun();
            Console.ReadKey();
        }
    }

這些線程都是在主線程中完成的,我們沒有創建任何額外的線程,

2.asyncawait結構

如果一個程序調用某個方法,等待其執行所有處理后才繼續執行,這樣的方法為同步方法,

異步方法為處理完成之前就返回到調用方法,

c#的async/await特性可以創建並使用異步方法,該特性由三個部分組成,

調用方法:該方法調用異步方法,然后在異步方法執行其任務的時候繼續執行,

異步方法:該方法執行異步工作,然后立即返回到調用方法

await表達式:用於異步方法內部,指明需要異步執行的任務,一個異步方法可以包含任意多個await表達式,如果一個不包含編譯器會發出警告,

調用方法如下:

 class Program
    {
        static void Main(string[] args)
        {
            Task<int> value = DoAsyncStuff.CalculateSumAsync(5, 6); // 調用方法
            Console.WriteLine("value:{0}", value.Result);
            Console.ReadKey();
        }
    }

異步方法如下:

 static class DoAsyncStuff
    {
        public static async Task<int> CalculateSumAsync(int n1, int n2)
        {
            int sum = await Task.Run(() => GetSum(n1, n2)); // 異步方法 await表達式
            return sum;
        }

        private static int GetSum(int n1, int n2)
        {
            return n1 + n2;
        }
    }

3.什么是異步方法

語法上,異步方法具有如下特點:
方法頭包含async方法修飾符,
包含一個或多個await表達式,
必須具備以下三種返回類型:Task<T>,Task,void,
異步方法的參數可以為任意類型的任意數量,但不能為out和ref參數,
按照約定,異步方法的名稱應該以Async為后綴,
除了方法以外,lambda表達式和匿名方法也可以作為異步對象,

使用返回Task<int>對象的異步方法

class Program
    {
        static void Main(string[] args)
        {
            Task<int> value = DoAsyncStuff.CalculateSumAsync(5, 6);
            Console.WriteLine("value:{0}", value.Result);
            Console.ReadKey();
        }
    }

    static class DoAsyncStuff
    {
        public static async Task<int> CalculateSumAsync(int n1, int n2)
        {
            int sum = await Task.Run(() => GetSum(n1, n2));
            return sum;
        }

        private static int GetSum(int n1, int n2)
        {
            return n1 + n2;
        }
    }

使用返回Task對象的異步方法

 class Program
    {
        static void Main(string[] args)
        {
            Task value = DoAsyncStuff.CalculateSumAsync(5, 6);
            value.Wait();
            Console.WriteLine("Async stuff is done");
            Console.ReadKey();
        }
    }

    static class DoAsyncStuff
    {
        public static async Task CalculateSumAsync(int n1, int n2)
        {
            int sum = await Task.Run(() => GetSum(n1, n2));
            Console.WriteLine("sum:{0}", sum);
        }

        private static int GetSum(int n1, int n2)
        {
            return n1 + n2;
        }
    }

使用“調用並忘記”的異步方法

 class Program
    {
        static void Main(string[] args)
        {
            DoAsyncStuff.CalculateSumAsync(5, 6);
            Thread.Sleep(200);
            Console.WriteLine("Program Exiting");
            Console.ReadKey();
        }
    }

    static class DoAsyncStuff
    {
        public static async void CalculateSumAsync(int n1, int n2)
        {
            int sum = await Task.Run(() => GetSum(n1, n2));
            Console.WriteLine("sum:{0}", sum);
        }

        private static int GetSum(int n1, int n2)
        {
            return n1 + n2;
        }
    }

qq


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM