引言
隨著 .NET 技術(shù)的發(fā)展,異步編程模型逐漸成為現(xiàn)代應(yīng)用程序開發(fā)中的標(biāo)準(zhǔn)實(shí)踐之一。.NET 4.5 引入了 Task
類,極大地簡化了異步編程的過程。然而,許多遺留系統(tǒng)仍在使用 .NET 4.0 或更低版本,這些版本并未直接支持 Task
類的全部功能。為此,我們開發(fā)了 TaskExCum
組件,旨在為 .NET 4.0 提供與 .NET 4.5 相似的 Task
功能,包括 Task.Run()
和 Task.WhenAll()
方法。
組件概述
TaskExCum
是一個靜態(tài)類,提供了以下主要功能:
實(shí)現(xiàn)步驟
接下來,我們將詳細(xì)講解 TaskExCum
組件的實(shí)現(xiàn)步驟,以便讀者能夠更好地理解其工作原理,并將其應(yīng)用于自己的項(xiàng)目中。
步驟 1: 創(chuàng)建 TaskExCum
類
首先,我們需要創(chuàng)建一個靜態(tài)類 TaskExCum
,并在其中定義靜態(tài)方法。
public static class TaskExCum{
}
步驟 2: 實(shí)現(xiàn) Run
方法
Run
方法允許開發(fā)者異步執(zhí)行任務(wù),并獲取任務(wù)的結(jié)果。我們?yōu)?nbsp;Run
方法提供了兩種重載形式,分別用于執(zhí)行無返回值的操作(Action
)和有返回值的操作(Func<TResult>
)。
public static Task<TResult> Run<TResult>(Func<TResult> function){#if NET45
return Task.Run(function);#else
return Task.Factory.StartNew(
function,
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default
);#endif}public static Task Run(Action action){#if NET45
return Task.Run(action);#else
return Task.Factory.StartNew(
action,
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default
);#endif}
詳細(xì)解釋:
步驟 3: 實(shí)現(xiàn) WhenAll
方法
WhenAll
方法用于等待多個任務(wù)完成,并收集所有任務(wù)的結(jié)果。我們?yōu)?nbsp;WhenAll
方法提供了多種重載形式,以支持不同類型的任務(wù)集合。
public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks){#if NET45
return Task.WhenAll(tasks);#else
return WhenAllCore(tasks);#endif}public static Task<TResult[]> WhenAll<TResult>(params Task<TResult>[] tasks){#if NET45
return Task.WhenAll(tasks);#else
return WhenAllCore(tasks);#endif}public static Task WhenAll(IEnumerable<Task> tasks){#if NET45
return Task.WhenAll(tasks);#else
return WhenAllCore(tasks);#endif}
詳細(xì)解釋:
步驟 4: 實(shí)現(xiàn) WhenAllCore
方法
WhenAllCore
方法是 WhenAll
方法的核心實(shí)現(xiàn),負(fù)責(zé)處理任務(wù)集合,等待所有任務(wù)完成,并收集結(jié)果或異常信息。
private static Task WhenAllCore(IEnumerable<Task> tasks){
return WhenAllCore(tasks, (completedTasks, tcs) => tcs.TrySetResult(null));
}private static Task<TResult[]> WhenAllCore<TResult>(IEnumerable<Task<TResult>> tasks){
return WhenAllCore(tasks.Cast<Task>(), (completedTasks, tcs) =>
{
tcs.TrySetResult(completedTasks.Select(t => ((Task<TResult>)t).Result).ToArray());
});
}private static Task<TResult> WhenAllCore<TResult>(IEnumerable<Task> tasks, Action<Task[], TaskCompletionSource<TResult>> setResultAction){
if (tasks == null)
{
throw new ArgumentNullException("tasks");
}
Contract.EndContractBlock();
Contract.Assert(setResultAction != null);
var tcs = new TaskCompletionSource<TResult>();
var array = (tasks as Task[]) ?? tasks.ToArray();
if (array.Length == 0)
{
setResultAction(array, tcs);
}
else
{
Task.Factory.ContinueWhenAll(array, completedTasks =>
{
var exceptions = new List<Exception>();
bool hasCanceled = false;
foreach (var task in completedTasks)
{
if (task.IsFaulted)
{
exceptions.AddRange(task.Exception.InnerExceptions);
}
else if (task.IsCanceled)
{
hasCanceled = true;
}
}
if (exceptions.Count > 0)
{
tcs.TrySetException(exceptions);
}
else if (hasCanceled)
{
tcs.TrySetCanceled();
}
else
{
setResultAction(completedTasks, tcs);
}
}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
return tcs.Task;
}
詳細(xì)解釋:
參數(shù)驗(yàn)證:檢查傳入的任務(wù)集合是否為 null
,如果是,則拋出 ArgumentNullException
。
TaskCompletionSource:創(chuàng)建一個 TaskCompletionSource
對象,用于管理任務(wù)的完成狀態(tài)。
任務(wù)轉(zhuǎn)換:將任務(wù)集合轉(zhuǎn)換為數(shù)組,以便于后續(xù)處理。
任務(wù)數(shù)量檢查:如果任務(wù)集合為空,直接調(diào)用 setResultAction
設(shè)置結(jié)果。
等待所有任務(wù)完成:使用 Task.Factory.ContinueWhenAll
方法等待所有任務(wù)完成。
異常處理:遍歷已完成的任務(wù),收集所有失敗任務(wù)的異常信息。
取消處理:檢查是否有任務(wù)被取消。
設(shè)置結(jié)果:如果沒有異常且沒有任務(wù)被取消,調(diào)用 setResultAction
設(shè)置結(jié)果。
TaskScheduler.Default:這里再次使用 TaskScheduler.Default
,確保任務(wù)在默認(rèn)的線程池中執(zhí)行,而不是每次都啟動新的線程。
步驟 5: 添加異常處理邏輯
為了確保組件的健壯性,我們還需要在 WhenAllCore
方法中添加異常處理邏輯,確保所有異常都能被捕獲并正確處理。
private static void AddPotentiallyUnwrappedExceptions(ref List<Exception> targetList, Exception exception){
var ex = exception as AggregateException;
Contract.Assert(exception != null);
Contract.Assert(ex == null || ex.InnerExceptions.Count > 0);
if (targetList == null)
{
targetList = new List<Exception>();
}
if (ex != null)
{
targetList.Add(ex.InnerExceptions.Count == 1 ? ex.InnerExceptions[0] : ex);
}
else
{
targetList.Add(exception);
}
}
詳細(xì)解釋:
異常類型檢查:檢查傳入的異常是否為 AggregateException
。
異常列表初始化:如果 targetList
為 null
,則初始化一個新的列表。
異常添加:根據(jù)異常的類型,將異?;蚱鋬?nèi)部異常添加到列表中。
示例代碼
為了幫助讀者更好地理解如何使用 TaskExCum
組件,下面是一些示例代碼。
示例 1: 使用 Run
方法
using System;using System.Threading.Tasks;class Program{
static void Main(string[] args)
{
try
{
string result = TaskExCum.Run(() => "Hello from Task!").Result;
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
示例 2: 使用 WhenAll
方法
using System;using System.Linq;using System.Threading.Tasks;class Program{
static void Main(string[] args)
{
try
{
var tasks = Enumerable.Range(1, 5).Select(i => TaskExCum.Run(() => i * i)).ToArray();
int[] results = TaskExCum.WhenAll(tasks).Result;
foreach (var result in results)
{
Console.WriteLine(result);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
轉(zhuǎn)自https://www.cnblogs.com/Bob-luo/p/18515670
該文章在 2024/11/6 9:24:43 編輯過