如題
先說異步連接的超時:
原理:異步連接,獲取狀態。阻止主進程等待異步進程返回。指定異步進程超時時間,這段時間內,如果異步連接沒有返回,則以未完成狀態返回,主進程繼續。
根據對獲取到的狀態的識別,來判斷是超時還是收到回應而使進程繼續。再分別處理。
代碼:
static void Main(string[] args) { for (int i = 20; i <= 25; i++) { TcpClient tcp = new TcpClient(); IAsyncResult async = tcp.BeginConnect(IPAddress.Parse("120.27.234.XXX"), i, null, null); async.AsyncWaitHandle.WaitOne(1000); if (async.IsCompleted) { Console.WriteLine($"{i} is open."); } else { Console.WriteLine($"{i} is closed."); ; } tcp.Close(); } Console.WriteLine("ok"); Console.ReadKey(); }
關於異步:
除了上面的類對象提供異步方法以外,所有的委托都可以異步執行。例如:
static void Main(string[] args) { Action<string> action = sayhi; Func<int,int,int> func = add; IAsyncResult r1,r2; r1 = action.BeginInvoke("張三",null,null); r1.AsyncWaitHandle.WaitOne(1000); if (r1.IsCompleted) { Console.WriteLine($"ok1"); } else { Console.WriteLine($"no1"); ; } r2 =func.BeginInvoke(1, 2, (g)=>myCallBack("王子","公主"), null); r2.AsyncWaitHandle.WaitOne(1000); if (r2.IsCompleted) { Console.WriteLine($"{func.EndInvoke(r2)}ok2"); } else { Console.WriteLine($"no2"); ; } Console.ReadKey(); } static int add(int x,int y) { return x + y; } static void sayhi(string x) { Console.WriteLine($"Hello,{x}!"); } static void myCallBack(string x,string y) { Console.WriteLine($"{x}和{y}終於幸福得生活在了一起"); }
結果:
如上例:
action和function委托都可以異步。注意func委托的返回值需要特別讀一下。
回調方法可以用“new AsyncCallback(方法名)”來聲明,也可以用lamda表達式。
用lamda表達式的時候,可以鑽漏洞輸入任意參數,見例子。
注意:寫在拉姆達表達式里面的參數是在方法運行的時候加載,而不是在方法初始化的時候加載。如果是變量就要小心了。
對於正常的回調(如Task回調),如果需要在一開始確定參數的值,需要用object對象state顯式指定。
而對於委托的begininvoke方法,里面的回調參數,是IAsyncResult類型。需要用它的“AsyncState”參數獲取傳入的object類型的內容(這一點跟代碼提示的內容不一樣)。也可以用拉姆達表達式去寫,如:
myaction.BeginInvoke(o=>MessageBox.Show(this,o.AsyncState.ToString()), "ok");
回調方法也可以為null。
回調方法必須帶一個object參數。可以為null。
當然,委托也可以同步調用,此處略。
我覺得如果沒有控制要求,委托異步就很好了。但從參數傳遞的復雜度來看,微軟似乎並不推薦這種用法。
有控制要求的,可以試試task,見另一篇文章。