C# Task任务详细讲解

13 篇文章 0 订阅

Task基础讲解

在C#中,Task 是用于表示异步操作的类。它属于 System.Threading.Tasks 命名空间,并允许你以异步方式执行代码,从而不阻塞主线程。这对于I/O密集型操作(如网络请求或文件读写)或CPU密集型任务非常有用,因为它们可以让应用程序在等待操作时继续处理其他任务。

举例

以下是关于 Task 使用的一些详细教学和编码例子:

1. 简单的 Task 使用

using System;

using System.Threading.Tasks;



class Program

{

    static async Task Main(string[] args) // Main 方法也可以是异步的

    {

        Console.WriteLine("开始一个异步任务...");

        Task myTask = DoSomethingAsync(); // 启动异步任务

        await myTask; // 等待任务完成

        Console.WriteLine("任务完成!");

    }



    static async Task DoSomethingAsync()

    {

        await Task.Run(() =>

        {

            // 模拟耗时操作

            Console.WriteLine("开始模拟耗时操作...");

            System.Threading.Thread.Sleep(2000); // 假设这里是一个耗时操作

            Console.WriteLine("模拟耗时操作结束!");

        });

    }

}

在这个例子中,DoSomethingAsync 方法返回一个 Task 对象,该对象表示一个异步操作。我们使用 Task.Run 来在另一个线程上执行耗时操作,并通过 await 关键字等待它完成。注意,为了使 await 关键字在 Main 方法中有效,我们需要将 Main 方法标记为 async。

2. 使用 Task.WhenAll 等待多个任务完成(入参可直接使用List<Task>集合)

using System;

using System.Threading.Tasks;



class Program

{

    static async Task Main(string[] args)

    {

        Console.WriteLine("开始多个异步任务...");

        Task task1 = Task.Run(() => DoWork("任务1"));

        Task task2 = Task.Run(() => DoWork("任务2"));

        Task task3 = Task.Run(() => DoWork("任务3"));



        // 等待所有任务完成

        await Task.WhenAll(task1, task2, task3);



        Console.WriteLine("所有任务都已完成!");

    }



    static void DoWork(string taskName)

    {

        Console.WriteLine($"{taskName} 开始工作...");

        System.Threading.Thread.Sleep(1000); // 模拟耗时工作

        Console.WriteLine($"{taskName} 工作完成!");

    }

}

在这个例子中,我们启动了三个异步任务,并使用 Task.WhenAll 来等待它们全部完成。Task.WhenAll 返回一个表示所有给定任务何时完成的新任务。

3. 使用 Task.WhenAny 等待任何一个任务完成(入参可直接使用List<Task>集合)

using System;

using System.Threading.Tasks;



class Program

{

    static async Task Main(string[] args)

    {

        Console.WriteLine("开始多个异步任务...");

        Task task1 = Task.Run(() => DoWork("任务A", 2000));

        Task task2 = Task.Run(() => DoWork("任务B", 1000));

        Task task3 = Task.Run(() => DoWork("任务C", 1500));



        // 等待任何一个任务完成

        Task completedTask = await Task.WhenAny(task1, task2, task3);



        Console.WriteLine($"第一个完成的任务是:{completedTask.Result}"); // 假设 DoWork 返回了一个结果



        // 等待剩余的任务完成(如果需要的话)

        await Task.WhenAll(task1, task2, task3);

        Console.WriteLine("所有任务都已完成!");

    }



    static string DoWork(string taskName, int delay)

    {

        Console.WriteLine($"{taskName} 开始工作...");

        System.Threading.Thread.Sleep(delay); // 模拟耗时工作

        Console.WriteLine($"{taskName} 工作完成!");

        return taskName + " 完成"; // 假设有一个返回结果

    }

}

在这个例子中,我们使用 Task.WhenAny 来等待任何一个任务完成。一旦有任务完成,我们就打印出它的结果,并继续等待其他任务完成。

这些例子展示了 Task 的基本用法,包括启动异步操作、等待任务完成以及处理多个任务。在实际应用中,你可能还会遇到更复杂的场景,如异常处理、取消操作等,这些都需要进一步学习和实践。

Task工厂讲解

在C#中,Task 工厂是一个用于创建和启动任务的类。它提供了多种方法来创建任务,包括使用 Task.Run 方法或 Task.Factory 属性的方法。虽然 Task.Run 是更现代和推荐的方式来创建和启动任务,但了解 Task.Factory 也是很有用的,因为它提供了更多的配置选项。

下面是使用 Task.Factory 创建任务的一些示例:

示例 1: 简单的任务创建

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // 使用 Task.Factory 创建一个任务
        Task task = Task.Factory.StartNew(() =>
        {
            Console.WriteLine("Hello from the task!");
        });

        // 等待任务完成
        task.Wait();

        Console.WriteLine("Task completed.");
    }
}

示例 2: 配置任务选项

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // 使用 TaskCreationOptions 和 CancellationToken 配置任务
        Task task = Task.Factory.StartNew(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("Working...");
                Thread.Sleep(500); // 模拟耗时操作

                // 检查取消请求
                if (Task.CurrentId.IsCancellationRequested)
                {
                    Console.WriteLine("Task cancellation requested.");
                    break;
                }
            }
        }, 
        TaskCreationOptions.LongRunning, // 指示任务可能是长时间运行的
        new CancellationTokenSource().Token); // 提供一个 CancellationToken,可用于取消任务

        // 等待一段时间后取消任务(仅作示例,实际中应根据需要决定何时取消)
        Thread.Sleep(3000);
        ((CancellationTokenSource)task.AsyncState).Cancel(); // 假设 AsyncState 保存了 CancellationTokenSource 的引用

        // 等待任务完成(或取消)
        try
        {
            task.Wait();
        }
        catch (AggregateException ae)
        {
            foreach (var inner in ae.InnerExceptions)
            {
                Console.WriteLine(inner.Message);
            }
        }

        Console.WriteLine("Main thread continues.");
    }
}


请注意,在上面的示例中,Task.CurrentId.IsCancellationRequested 是不正确的用法,因为 Task.CurrentId 是一个只读的属性,它表示当前正在执行的任务的 ID,而不是 CancellationToken。正确的做法是直接从 CancellationToken 属性中检查取消请求,如下所示:

if (cancellationToken.IsCancellationRequested)
{
    // 处理取消逻辑
}


在实际使用中,你应该将 CancellationToken 作为参数传递给你的任务方法,并在任务内部检查取消请求。

示例 3: 使用 Task.Run(推荐方法)

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main() // 注意:Main 方法现在也是异步的
    {
        // 使用 Task.Run 创建并启动一个任务(推荐方法)
        await Task.Run(() =>
        {
            Console.WriteLine("Hello from the task!");
        });

        Console.WriteLine("Task completed.");
    }
}


在大多数情况下,使用 Task.Run 是创建和启动新任务的推荐方法,因为它提供了简洁的语法,并且很容易与 await 关键字一起使用以实现异步编程。然而,Task.Factory 仍然在某些特定场景下(例如需要更细粒度的控制)是有用的。

  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C#中,Task是一个非常强大的多线程编程工具,它可以让开发者更方便地进行异步编程。下面是Task详细使用方法: 1. 创建Task对象 Task有多种创建方式,其中最常用的是使用静态方法Task.Factory.StartNew。 ```csharp Task task = Task.Factory.StartNew(() => { //执行异步操作 }); ``` 这里传递给StartNew方法的是一个委托,该委托包含了异步操作的代码。 2. 获取Task执行结果 在Task执行完成后,我们需要获取其执行结果。Task提供了几种方式来获取执行结果,最常用的是使用Task.Result属性。如果Task执行过程中发生了异常,需要使用Task.Exception属性来获取异常信息。 ```csharp Task<int> task = Task.Factory.StartNew(() => { //执行异步操作 return 1; }); int result = task.Result; ``` 这里Task的泛型参数指定了返回值类型,如果异步操作没有返回值,可以使用Task.Factory.StartNew(Action)方法来创建Task对象。 3. 等待Task执行完成 在某些情况下,我们需要等待Task执行完成后再进行后续操作。Task提供了几种等待方式,最常用的是使用Task.Wait方法。 ```csharp Task task = Task.Factory.StartNew(() => { //执行异步操作 }); task.Wait(); ``` 这里调用Task.Wait方法会阻塞当前线程,直到Task执行完成。 4. 处理Task执行结果 在Task执行完成后,我们需要处理其执行结果。Task提供了ContinueWith方法,可以让我们在Task执行完成后执行一些操作。 ```csharp Task<int> task = Task.Factory.StartNew(() => { //执行异步操作 return 1; }); task.ContinueWith(t => { //处理Task执行结果 int result = t.Result; }); ``` 这里传递给ContinueWith方法的是一个委托,该委托包含了Task执行完成后需要执行的代码。 以上就是Task的一些常用使用方法,利用Task可以更方便地进行异步编程。需要注意的是,在使用Task时需要注意线程安全问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laizhixue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值