非同步編程模式(一)

來源:互聯網
上載者:User

.net 的非同步編程技術主要分為兩個塊:

1、使用IAsyncResult 的非同步編程模式。

2、基於事件的非同步編程模式。

 

C#編譯器會為每個委託產生支援非同步執行的 BeginInvoke / EndInvoke 方法,從而將委託和非同步編程緊密聯絡起來了。

 

當同步執行程式時,如果執行到需要執行較長時間的代碼時,使用者必須等待,也會認為程式已經卡死或死機了。

同步程式的範例程式碼如下:

namespace CalculateFolderSizeNoAsync
{
class Program
{
//計算指定檔案夾的總容量
private static long CalculateFolderSize(string FolderName)
{
if (Directory.Exists(FolderName) == false)
{
throw new DirectoryNotFoundException("檔案夾不存在");
}

DirectoryInfo RootDir = new DirectoryInfo(FolderName);
//擷取所有的子檔案夾
DirectoryInfo[] ChildDirs = RootDir.GetDirectories();
//擷取當前檔案夾中的所有檔案
FileInfo[] files = RootDir.GetFiles();
long totalSize = 0;
//累加每個檔案的大小
foreach (FileInfo file in files)
{
totalSize += file.Length;
}
//對每個檔案夾執行同樣的計算過程:累加其下每個檔案的大小
//這是通過遞迴調用實現的
foreach (DirectoryInfo dir in ChildDirs)
{
totalSize += CalculateFolderSize(dir.FullName);
}
//返迴文件夾的總容量
return totalSize;
}

static void Main(string[] args)
{
long size;
string FolderName;


Console.WriteLine("請輸入檔案夾名稱(例如:C:\\Windows):");

FolderName = Console.ReadLine();


size = CalculateFolderSize(FolderName);

Console.WriteLine("\n檔案夾{0}的容量為:{1}位元組\n", FolderName , size);

Console.ReadKey();

}
}
}

程式中調用了CalculateFolderSize方法,如果此方法不返回,下面的代碼是不可能執行的。

如果這個方法執行時間很長,則使用者在方法返回前是看不到任何資訊的,他有可能會以為電腦死機了。

上述程式就是典型的程式同步執行模式。

能不能在調用方法後,不用等待方法執行完成就馬上執行下一條語句?

要實現 這個功能,就必須採用“非同步編程模式”

 

如下程式碼範例:

namespace AsyncCalculateFolderSize1
{
class Program
{
//計算指定檔案夾的總容量
private static long CalculateFolderSize(string FolderName)
{
if (Directory.Exists(FolderName) == false)
{
throw new DirectoryNotFoundException("檔案夾不存在");
}

DirectoryInfo RootDir = new DirectoryInfo(FolderName);

//擷取所有的子檔案夾
DirectoryInfo[] ChildDirs = RootDir.GetDirectories();
//擷取當前檔案夾中的所有檔案
FileInfo[] files = RootDir.GetFiles();
long totalSize = 0;
//累加每個檔案的大小
foreach (FileInfo file in files)
{
totalSize += file.Length;
}
//對每個檔案夾執行同樣的計算過程:累加其下每個檔案的大小
//這是通過遞迴調用實現的
foreach (DirectoryInfo dir in ChildDirs)
{
totalSize += CalculateFolderSize(dir.FullName);
}
//返迴文件夾的總容量
return totalSize;
}

//定義一個委託
public delegate long CalculateFolderSizeDelegate(string FolderName);

static void Main(string[] args)
{

//定義一個委託變數引用靜態方法CalculateFolderSize
CalculateFolderSizeDelegate d = CalculateFolderSize;

Console.WriteLine("請輸入檔案夾名稱(例如:C:\\Windows):");

string FolderName = Console.ReadLine();

//通過委託非同步呼叫靜態方法CalculateFolderSize
IAsyncResult ret=d.BeginInvoke(FolderName,null,null);

Console.WriteLine("正在計算中,請耐心等待……");
//阻塞,等到調用完成,取出結果
long size = d.EndInvoke(ret);

Console.WriteLine("\n計算完成。檔案夾{0}的容量為:{1}位元組\n", FolderName, size);

Console.ReadKey();
}
}


}

本樣本的非同步編程方式是通過委託來實現的。

通過建立一個引用靜態方法CalculateFolderSize 的委託變數d,第4句通過調用委派物件d 的 BeginInvoke 方法間接地調用靜態方法CalculateFolderSize 不在主線程中執行

,而在另一個輔助純種中與主線程代碼並行 執行,由於存在兩個並行的線程,所以啟動執行靜態方法CalculateFilderSize 之後,並不會等待其完成,而是馬上執行下一句,輸

出一句提示資訊。

 

從這個典型的非同步呼叫程式中,可以知道非同步呼叫 的一種通用的編程模式是:

//..............

//普通的代碼:處於同步執行模式

IAsyncResult ret = 委託變數.BeginInvoke(......); //啟動非同步呼叫

//可以在這一部分做其他一些事,程式處於非同步執行模式

用於儲存方法結果的變數 = 委託變數.EndInvoke(ret);  //結束非同步呼叫

//普通的代碼:處於同步執行模式

//...............

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.