1、什么是異步?
異步操作通常用於執行完成時間可能較長的任務,如打開大文件、連接遠程計算機或查詢數據庫=異步操作在主應用程序線程以外的線程中執行。應用程序調用方法異步執行某個操作時,應用程序可在異步方法執行其任務時繼續執行。
2、同步與異步的區別
同步(Synchronous):在執行某個操作時,應用程序必須等待該操作執行完成后才能繼續執行。
異步(Asynchronous):在執行某個操作時,應用程序可在異步操作執行時繼續執行。實質:異步操作,啟動了新的線程,主線程與方法線程並行執行。
3、異步和多線程的區別
我們已經知道, 異步和多線程並不是一個同等關系,異步是最終目的,多線程只是我們實現異步的一種手段。異步是當一個調用請求發送給被調用者,而調用者不用等待其結果的返回而可以做其它的事情。實現異步可以采用多線程技術或則交給另外的進程來處理。
簡單的說就是:異步線程是由線程池負責管理,而多線程,我們可以自己控制,當然在多線程中我們也可以使用線程池。
就拿網絡扒蟲而言,如果使用異步模式去實現,它使用線程池進行管理。異步操作執行時,會將操作丟給線程池中的某個工作線程來完成。當開始I/O操作的時候,異步會將工作線程還給線程池,這意味着獲取網頁的工作不會再占用任何CPU資源了。直到異步完成,即獲取網頁完畢,異步才會通過回調的方式通知線程池。可見,異步模式借助於線程池,極大地節約了CPU的資源。
注:DMA(Direct Memory Access)直接內存存取,顧名思義DMA功能就是讓設備可以繞過處理器,直接由內存來讀取資料。通過直接內存訪問的數據交換幾乎可以不損耗CPU的資源。在硬件中,硬盤、網卡、聲卡、顯卡等都有直接內存訪問功能。異步編程模型就是讓我們充分利用硬件的直接內存訪問功能來釋放CPU的壓力。
兩者的應用場景:
-
計算密集型工作,采用多線程。
-
IO密集型工作,采用異步機制。
C#異步代碼參考(async and await)
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncAwaitDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("main start..");
AsyncMethod();
Thread.Sleep(1000);
Console.WriteLine("main end..");
Console.ReadLine();
}
static async void AsyncMethod()
{
Console.WriteLine("start async");
var result = await MyMethod();
Console.WriteLine("end async");
//return 1;
}
static async Task<int> MyMethod()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Async start:" + i.ToString() + "..");
await Task.Delay(1000); //模擬耗時操作
}
return 0;
}
}
}
使用Wait()和GetAwaiter().GetResult()方法實現異步方法同步執行
using System;
using System.Threading.Tasks;
namespace AsyncTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Async Test job:");
Console.WriteLine("main start..");
Console.WriteLine("MyMethod()異步方法同步執行:");
MyMethod().Wait();//在main中等待async方法執行完成
int i = MyMethod().GetAwaiter().GetResult();//用於在main中同步獲取async方法的返回結果
Console.WriteLine("i:" + i);
Console.WriteLine("main end..");
Console.ReadKey(true);
}
static async Task<int> MyMethod()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Async start:" + i.ToString() + "..");
await Task.Delay(1000); //模擬耗時操作
}
return 0;
}
}
}
