C#使用多線程併發之異步委託IAsyncResult

使用委託開啓多線程(多線程深入)

1、用委託(Delegate)的BeginInvoke和EndInvoke方法操作線程 
BeginInvoke方法可以使用線程異步地執行委託所指向的方法。然後通過EndInvoke方法獲得方法的返回值(EndInvoke方法的返回值就是被調用方法的返回值),或是確定方法已經被成功調用。


class Program
{
private delegate int NewTaskDelegate(int ms);
private static int newTask(int ms)
{
Console.WriteLine("任務開始");
Thread.Sleep(ms);
Random random = new Random();
int n = random.Next(10000);
Console.WriteLine("任務完成");
return n;
}
static void Main(string[] args)
{
NewTaskDelegate task = newTask;
IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
//EndInvoke方法將被阻塞2秒
int result = task.EndInvoke(asyncResult);
Console.WriteLine(result);
Console.Read();
}
}

2、使用IAsyncResult.IsCompleted屬性來判斷異步調用是否完成

class Program
{
private delegate int NewTaskDelegate(int ms);
private static int newTask(int ms)
{
Console.WriteLine("任務開始");
Thread.Sleep(ms);
Random random = new Random();
int n = random.Next(10000);
Console.WriteLine("任務完成");
return n;
}
static void Main(string[] args)
{
NewTaskDelegate task = newTask;
IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
//等待異步執行完成
while (!asyncResult.IsCompleted)
{
Console.Write("*");
Thread.Sleep(100);
}
// 由於異步調用已經完成,因此, EndInvoke會立刻返回結果
int result = task.EndInvoke(asyncResult);
Console.WriteLine(result);
Console.Read();
}
}

3、使用WaitOne方法等待異步方法執行完成 
WaitOne的第一個參數表示要等待的毫秒數,在指定時間之內,WaitOne方法將一直等待,直到異步調用完成,併發出通知,WaitOne方法才返回true。當等待指定時間之後,異步調用仍未完成,WaitOne方法返回false,如果指定時間爲0,表示不等待,如果爲-1,表示永遠等待,直到異步調用完成。


class Program
{
private delegate int NewTaskDelegate(int ms);
private static int newTask(int ms)
{
Console.WriteLine("任務開始");
Thread.Sleep(ms);
Random random = new Random();
int n = random.Next(10000);
Console.WriteLine("任務完成");
return n;
}
static void Main(string[] args)
{
NewTaskDelegate task = newTask;
IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
//等待異步執行完成
while (!asyncResult.AsyncWaitHandle.WaitOne(100, false))
{
Console.Write("*");
}
int result = task.EndInvoke(asyncResult);
Console.WriteLine(result);
Console.Read();
}
}

4、使用回調方式返回結果 
要注意的是“my.BeginInvoke(3,300, MethodCompleted, my)”,BeginInvoke方法的參數傳遞方式: 
前面一部分(3,300)是其委託本身的參數。 
倒數第二個參數(MethodCompleted)是回調方法委託類型,他是回調方法的委託,此委託沒有返回值,有一個IAsyncResult類型的參數,當method方法執行完後,系統會自動調用MethodCompleted方法。 
最後一個參數(my)需要向MethodCompleted方法中傳遞一些值,一般可以傳遞被調用方法的委託,這個值可以使用IAsyncResult.AsyncState屬性獲得。

class Program
{
private delegate int MyMethod(int second, int millisecond);
//線程執行方法
private static int method(int second, int millisecond)
{
Console.WriteLine("線程休眠" + (second * 1000 + millisecond) + "毫秒");
Thread.Sleep(second * 1000 + millisecond);
Random random = new Random();
return random.Next(10000);
}
//回調方法
private static void MethodCompleted(IAsyncResult asyncResult)
{
if (asyncResult == null || asyncResult.AsyncState == null)
{
Console.WriteLine("回調失敗!!!");
return;
}
int result = (asyncResult.AsyncState as MyMethod).EndInvoke(asyncResult);
Console.WriteLine("任務完成,結果:" + result);
}
static void Main(string[] args)
{
MyMethod my = method;
IAsyncResult asyncResult = my.BeginInvoke(3,300, MethodCompleted, my);
Console.WriteLine("任務開始");
Console.Read();
}
}
  •  

5、其他組件的BeginXXX和EndXXX方法 
在其他的.net組件中也有類似BeginInvoke和EndInvoke的方法,如System.Net.HttpWebRequest類的BeginGetResponse和EndGetResponse方法。其使用方法類似於委託類型的BeginInvoke和EndInvoke方法,例如


class Program
{
//回調函數
private static void requestCompleted(IAsyncResult asyncResult)
{
if (asyncResult == null || asyncResult.AsyncState==null)
{
Console.WriteLine("回調失敗");
return;
}
HttpWebRequest hwr = asyncResult.AsyncState as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse)hwr.EndGetResponse(asyncResult);
StreamReader sr = new StreamReader(response.GetResponseStream());
string str = sr.ReadToEnd();
Console.WriteLine("返回流長度:"+str.Length);
}
static void Main(string[] args)
{
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create("http://www.baidu.com");
//異步請求
IAsyncResult asyncResult = request.BeginGetResponse(requestCompleted, request);
Console.WriteLine("任務開始");
Console.Read();
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章