BeginInvoke、IAsyncResult、EndInvoke、AsyncCallback
一、BeginInvoke
語法:
IAsyncResult delegate.BeginInvoke([parameters], AsyncCallback callback, object @object);
using System;
using System.Threading;
namespace ConsoleApp1
{
public class AsyncDemo
{
public string TestMethod(string name, int callDuration)
{
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 開始");
Thread.Sleep(callDuration);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 結束");
return name + " complete";
}
}
public delegate string AsyncMethodCaller(string name, int callDuration);
class Program
{
public static void Main()
{
AsyncDemo ad = new AsyncDemo();
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
IAsyncResult result10 = caller.BeginInvoke("任務10秒", 10000, null, null);
IAsyncResult result15 = caller.BeginInvoke("任務15秒", 15000, null, null);
IAsyncResult result20 = caller.BeginInvoke("任務20秒", 20000, null, null);
Thread.Sleep(5000);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + "主執行緒5秒");
Console.ReadKey();
}
}
}
執行畫面為
說明:
1、範例上共有四個要執行的項目,分別是「主執行緒5秒」、「任務10秒」、「任務15秒」、「任務20秒」,
如果是使用同步作法的話,則總共會花 5 + 10 + 15 + 20 = 50 秒的時間;
但使用非同步作法的話,由於要執行的四個項目會同時間開始處理,
故最多只會花到 20 秒時間,這就是同步與非同步的最大不同之處。
2、此範例是利用委派所提供的 BeginInvoke 方法去實作非同步,
BeginInvoke 方法的意思為將一任務加入非同步處理。
3、注意 BeginInvoke 只支援在 .Net Framework 4.8 以下,而不能在 .Net Core 上跑。
二、IAsyncResult
IAsyncResult 是一個介面,有以下屬性
而 AsyncResult 是實作類別
AsyncState 屬性是用來取得 user-defined object。
你可以利用 IsCompleted 屬性來輪詢「任務20秒」是否完成任務。
using System;
using System.Threading;
namespace ConsoleApp1
{
public class AsyncDemo
{
public string TestMethod(string name, int callDuration)
{
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 開始");
Thread.Sleep(callDuration);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 結束");
return name + " complete";
}
}
public delegate string AsyncMethodCaller(string name, int callDuration);
class Program
{
public static void Main()
{
AsyncDemo ad = new AsyncDemo();
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
IAsyncResult result10 = caller.BeginInvoke("任務10秒", 10000, null, null);
IAsyncResult result15 = caller.BeginInvoke("任務15秒", 15000, null, null);
IAsyncResult result20 = caller.BeginInvoke("任務20秒", 20000, null, null);
while (result20.IsCompleted == false)
{
Thread.Sleep(1000);
Console.WriteLine(".");
}
Thread.Sleep(5000);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + "主執行緒5秒");
Console.ReadKey();
}
}
}
執行畫面為
三、EndInvoke
語法:
delegate_type delegate.EndInvoke(IAsyncResult result);
using System;
using System.Threading;
namespace ConsoleApp1
{
public class AsyncDemo
{
public string TestMethod(string name, int callDuration)
{
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 開始");
Thread.Sleep(callDuration);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 結束");
return name + " complete";
}
}
public delegate string AsyncMethodCaller(string name, int callDuration);
class Program
{
public static void Main()
{
AsyncDemo ad = new AsyncDemo();
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
IAsyncResult result10 = caller.BeginInvoke("任務10秒", 10000, null, null);
IAsyncResult result15 = caller.BeginInvoke("任務15秒", 15000, null, null);
IAsyncResult result20 = caller.BeginInvoke("任務20秒", 20000, null, null);
string returnValue = caller.EndInvoke(result20);
Console.WriteLine(returnValue);
Thread.Sleep(5000);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + "主執行緒5秒");
Console.ReadKey();
}
}
}
執行畫面為
說明:
1、在 Main() 裡,當執行到 EndInvoke() 方法時,將會等待其任務完成後才會繼續執行 Main() 之後的內容;
其 EndInvoke() 方法的意思就是等待指定任務完成才會繼續執行。
四、AsyncCallback
AsyncCallback 是個委派型別,其用來當一任務完成時,執行所指定的方法。
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace ConsoleApp1
{
public class AsyncDemo
{
public string TestMethod(string name, int callDuration)
{
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 開始");
Thread.Sleep(callDuration);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + " " + name + " 結束");
return name + " complete";
}
}
public delegate string AsyncMethodCaller(string name, int callDuration);
class Program
{
public static void Main()
{
AsyncDemo ad = new AsyncDemo();
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
IAsyncResult result10 = caller.BeginInvoke("任務10秒", 10000, null, null);
IAsyncResult result15 = caller.BeginInvoke("任務15秒", 15000, null, null);
IAsyncResult result20 = caller.BeginInvoke("任務20秒", 20000, null, null);
IAsyncResult result = caller.BeginInvoke("任務25秒", 25000, new AsyncCallback(CallbackMethod), "(((任務25秒)))");
Thread.Sleep(5000);
Console.WriteLine("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId + "主執行緒5秒");
Console.ReadKey();
}
public static void CallbackMethod(IAsyncResult ar)
{
//從 IAsyncResult 轉型成 AsyncResult
AsyncResult result = (AsyncResult)ar;
//取得本身的委派方法
AsyncMethodCaller caller = (AsyncMethodCaller)result.AsyncDelegate;
//目地只是為了取得其回傳值
string returnValue = caller.EndInvoke(ar);
//Gets a user-defined object
string oUserDefined = (string)ar.AsyncState;
Console.WriteLine(oUserDefined + "-" + returnValue);
}
}
}
執行畫面為
參考資料: