天天看點

一起談.NET技術,C#基礎之委托異步

  大家知道委托就相當于C++裡面的函數指針,相信大家都很很了解,看看如下簡單代碼來回想一下委托

public delegate void Ad();

xu xus = new xu();

Ad b = new Ad(xus.Add);

b += xus.ex;

b();

Console.ReadLine();

class xu

{

public void Add()

//Thread.Sleep(5000);

Console.WriteLine("sssssssssssssssssssss");

}

public void ex()

Console.WriteLine("aaaaaaaaaaaaaaaaaaaaa");

  這裡我們看見 定義了一個ADD 的委托沒有參數沒有傳回值 然後把委托指向ADD 和ex 兩個方法(多點傳播委托) 然後執行b()  執行之後 結果大家應該知道 就是執行了這2個方法列印出 "ssssssssssssss"于"aaaaaaaaaaaaaaaa"。那如果變成下面這個形式呢?

public delegate int Ad(int x,int y);

static void Main(string[] args)

Ad a = new Ad(Add);

a += (int x, int y) => { return x - y; };

Console.WriteLine(a(3,2));

static int Add(int x, int y)

//Thread.Sleep(2000);

return x + y;

static int ex(int x, int y)

return x - y;

  這段代碼 也是執行一個多點傳播委托 但是輸出的結果會是什麼樣的呢 答案是 輸出1,為什麼前面那個委托會輸出2個方法 而這個委托隻會輸出第二個方法的傳回值?如果我們也想輸出2個傳回值怎麼辦呢?其實很簡單 代碼如下

Delegate[] d = a.GetInvocationList();

for (int i = 0; i < d.Length; i++)

if (d[i] is Ad)

Ad s = (Ad)d[i];

Console.WriteLine(s(3, 2));

// Thread.Sleep(2000);

  這裡我們使用了一個GetInvocationList 方法來傳回多點傳播委托的調用清單 然後轉化ad 然後循環調用 最後顯示的結果就是5,1。委托的 複習我們就看到這裡 現在回到正題 看看委托的異步調用。

Console.WriteLine(a(3, 3));

Console.WriteLine("start");

Thread.Sleep(2000);

  運作這段代碼 會先停頓2秒鐘之後再顯示6 和start 因為我使用了sleep這個方法 它使該線程休眠2秒鐘,是以會在2秒之後顯示資訊,但是這對使用者體驗來說是非常糟糕的,那我們怎麼改善呢?看看如下代碼

// Console.WriteLine("start");

IAsyncResult isa= a.BeginInvoke(3, 3, null, null);

while (!isa.IsCompleted)

Console.WriteLine("未完成");

int s= a.EndInvoke(isa);

Console.WriteLine(s.ToString());

  這裡我們使用了begininvoke方法來異步執行 委托方法傳回一個IAsyncResult 類型的值 代表委托執行的狀态,使用一個while循環 來判斷IsCompleted 如果沒有完成異步調用則不斷顯示“未完成” 如果完成endinvoke 則傳回結果。但是這裡需要不斷的詢問操作完成狀态 那麼我們怎樣讓委托異步調用完成之後主動通知我們呢? 看看如下代碼

IAsyncResult isa= a.BeginInvoke(3, 3, new AsyncCallback(call), "edit by xyl");

//執行你想執行的代碼 這裡我們還是用IsCompleted來代替

static void call(IAsyncResult isa)

AsyncResult ar = (AsyncResult)isa;

Ad a = (Ad)ar.AsyncDelegate;

Console.WriteLine("this is {0},{1}",a.EndInvoke(isa),ar.AsyncState);

  這裡我們使用了一個call方法 注意它是沒有傳回值的。把IAsyncResult轉換成AsyncResult注意少了個I然後轉換成AD 類型的委托 最後endinvoke 來傳回值 這樣在委托異步執行完成之後會自動通知方法。呵呵 好了今天就說到這裡吧。如果有說的不對的地方歡迎指正 大家一起學習一起進步。