游戏攻略

实现.NET 4.0下的Task类相似功能组件

栏目:游戏攻略 日期: 作者:游戏资讯

实现 .NET 4.0 下的 Task 类相似功能:TaskExCum 组件详解

引言

随着 .NET 技术的发展,异步编程模型逐渐成为现代应用程序开发中的标准实践之一。.NET 4.5 引入了 Task 类,极大地简化了异步编程的过程。然而,许多遗留系统仍在使用 .NET 4.0 或更低版本,这些版本并未直接支持 Task 类的全部功能。为此,我们开发了 TaskExCum 组件,旨在为 .NET 4.0 提供与 .NET 4.5 相似的 Task 功能,包括 Task.Run() Task.WhenAll() 方法。

组件概述

TaskExCum 是一个静态类,提供了以下主要功能:

  • Run 方法:用于异步执行任务,并获取任务的结果。
  • WhenAll 方法:用于等待多个任务完成,并收集所有任务的结果。

实现步骤

接下来,我们将详细讲解 TaskExCum 组件的实现步骤,以便读者能够更好地理解其工作原理,并将其应用于自己的项目中。

步骤 1: 创建 TaskExCum

首先,我们需要创建一个静态类 TaskExCum ,并在其中定义静态方法。

public static class TaskExCum
{
    // 方法定义将在后续步骤中添加
}

步骤 2: 实现 Run 方法

Run 方法允许开发者异步执行任务,并获取任务的结果。我们为 Run 方法提供了两种重载形式,分别用于执行无返回值的操作( Action )和有返回值的操作( Func<TResult> )。

public static Task<TResult> Run<TResult>(Func<TResult> function)
{
#if NET45
    // 如果目标框架是 .NET 4.5 或更高版本,使用 Task.Run 方法
    return Task.Run(function);
#else
    // 如果目标框架是 .NET 4.0,使用 Task.Factory.StartNew 方法
    return Task.Factory.StartNew(
        function, 
        CancellationToken.None, 
        TaskCreationOptions.None, 
        TaskScheduler.Default
    );
#endif
}

public static Task Run(Action action)
{
#if NET45
    // 如果目标框架是 .NET 4.5 或更高版本,使用 Task.Run 方法
    return Task.Run(action);
#else
    // 如果目标框架是 .NET 4.0,使用 Task.Factory.StartNew 方法
    return Task.Factory.StartNew(
        action, 
        CancellationToken.None, 
        TaskCreationOptions.None, 
        TaskScheduler.Default
    );
#endif
}

详细解释

  • 条件编译 :使用 #if NET45 编译符号,当项目目标框架为 .NET 4.5 及更高版本时,使用 Task.Run 方法。
  • Task.Factory.StartNew :当项目目标框架为 .NET 4.0 时,使用 Task.Factory.StartNew 方法来启动任务。
    • CancellationToken.None :表示没有取消令牌,任务不会被外部取消。
    • TaskCreationOptions.None :表示没有特殊的任务创建选项。
    • TaskScheduler.Default :这是关键点之一。 TaskScheduler.Default 表示使用默认的线程池调度器,这意味着任务会在线程池中的一个线程上执行,而不是每次都启动一个新的线程。这有助于提高性能和资源利用率。

步骤 3: 实现 WhenAll 方法

WhenAll 方法用于等待多个任务完成,并收集所有任务的结果。我们为 WhenAll 方法提供了多种重载形式,以支持不同类型的任务集合。

public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks)
{
#if NET45
    // 如果目标框架是 .NET 4.5 或更高版本,使用 Task.WhenAll 方法
    return Task.WhenAll(tasks);
#else
    // 如果目标框架是 .NET 4.0,调用 WhenAllCore 方法
    return WhenAllCore(tasks);
#endif
}

public static Task<TResult[]> WhenAll<TResult>(params Task<TResult>[] tasks)
{
#if NET45
    // 如果目标框架是 .NET 4.5 或更高版本,使用 Task.WhenAll 方法
    return Task.WhenAll(tasks);
#else
    // 如果目标框架是 .NET 4.0,调用 WhenAllCore 方法
    return WhenAllCore(tasks);
#endif
}

public static Task WhenAll(IEnumerable<Task> tasks)
{
#if NET45
    // 如果目标框架是 .NET 4.5 或更高版本,使用 Task.WhenAll 方法
    return Task.WhenAll(tasks);
#else
    // 如果目标框架是 .NET 4.0,调用 WhenAllCore 方法
    return WhenAllCore(tasks);
#endif
}

详细解释

  • 条件编译 :使用 #if NET45 编译符号,当项目目标框架为 .NET 4.5 及更高版本时,使用 Task.WhenAll 方法。
  • WhenAllCore :当项目目标框架为 .NET 4.0 时,调用 WhenAllCore 方法来实现相同的功能。

步骤 4: 实现 WhenAllCore 方法

WhenAllCore 方法是 WhenAll 方法的核心实现,负责处理任务集合,等待所有任务完成,并收集结果或异常信息。

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;
}

详细解释

  • 参数验证 :检查传入的任务集合是否为 null ,如果是,则抛出 ArgumentNullException
  • TaskCompletionSource :创建一个 TaskCompletionSource 对象,用于管理任务的完成状态。
  • 任务转换 :将任务集合转换为数组,以便于后续处理。
  • 任务数量检查 :如果任务集合为空,直接调用 setResultAction 设置结果。
  • 等待所有任务完成 :使用 Task.Factory.ContinueWhenAll 方法等待所有任务完成。
    • 异常处理 :遍历已完成的任务,收集所有失败任务的异常信息。
    • 取消处理 :检查是否有任务被取消。
    • 设置结果 :如果没有异常且没有任务被取消,调用 setResultAction 设置结果。
    • TaskScheduler.Default :这里再次使用 TaskScheduler.Default ,确保任务在默认的线程池中执行,而不是每次都启动新的线程。

步骤 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)
    {
        // 如果异常是 AggregateException,添加其内部异常
        targetList.Add(ex.InnerExceptions.Count == 1 ? ex.InnerExceptions[0] : ex);
    }
    else
    {
        // 否则,直接添加异常
        targetList.Add(exception);
    }
}

详细解释

  • 异常类型检查 :检查传入的异常是否为 AggregateException
  • 异常列表初始化 :如果 targetList null ,则初始化一个新的列表。
  • 异常添加 :根据异常的类型,将异常或其内部异常添加到列表中。

示例代码

为了帮助读者更好地理解如何使用 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}");
        }
    }
}

结论

通过 TaskExCum 组件,即使是在 .NET 4.0 这样的老框架版本中,我们也能够享受到现代异步编程模型带来的便利。希望这个组件能够帮助那些需要在旧版 .NET 框架中实现异步操作的开发者们,提高他们的开发效率和代码质量。如果你有任何建议或改进意见,欢迎留言交流!


详情请看: https://www.cnblogs.com/Bob-luo/p/18515670
以上就是关于 TaskExCum 组件的详细介绍。希望通过这篇文章,读者能够更好地理解和使用这个组件,从而在自己的项目中实现高效的异步编程。如果有任何问题或需要进一步的帮助,请随时留言!

关键词:

相关资讯

  • 新月同行主线第六章攻略

    新月同行游戏的主线第六章有一定的攻略难度。如果玩家角色搭配不当,在战斗中很容易失败。本攻略将为玩家提供第六章最佳阵容推荐和详细...
  • 实现.NET 4.0下的Task类相似功能组件

    实现 .NET 4.0 下的 Task 类相似功能:TaskExCum 组件详解 引言 随着 ....
  • 《e英语宝》加入班级方法

    E英语宝是一款专为英语学习设计的应用程序,因其丰富的学习资源和便捷的操作方式而备受师生和家长的喜爱。对于新用户来说,快速加入班...
  • 《原神》万火之瓯幻写灵位置

    在《原神》中,万火之瓯幻写灵的位置一直是玩家们关注的焦点。游戏中共有46个幻写灵,但很多玩家花费了很长时间也未能找齐所有的幻写...
  • 新月同行银峰技能强度详解

    新月同行银峰是游戏内五星前排生存角色之一,拥有非常高的坦度,能够很好的保护队伍成员。下面将对新月同行银峰的技能强度进行全面解析...
  • 神奇海洋今日答案2024.10.30

    神奇海洋科普问答10.30答案是蛏子体内有一根透明的“棍子”,猜猜是什么器官。神奇海洋是蚂蚁森林全新推出的海洋公益玩法。今天的...