C# 中 Task 的解析与应用实例

173 阅读1分钟

Task 可以用来封装一个异步操作,使其可以在不阻塞主线程的情况下执行,并在操作完成后获取结果;还可以使用 Task 可以轻松地并行处理多个任务,并等待它们全部完成


//两种不同的调用语法,本质都一样
await MyMethod1Async();
await MyMethod2Async();
await ParallelProcessingAsync();
static async Task<int> LongRunningOperationAsync()
{
    // 模拟耗时操作
    await Task.Delay(1000);
    return 42; // 假设这是耗时操作的返回结果
}
static async Task MyMethod1Async()
{
    int result = await Task.Run(() => LongRunningOperationAsync());
    Console.WriteLine($"操作结果: {result}");
}

static async Task MyMethod2Async()
{
    int result = await LongRunningOperationAsync();
    Console.WriteLine($"操作结果: {result}");
}

static async Task ParallelProcessingAsync()
{
    Task<int> task1 = Task.Run(() => LongRunningOperationAsync());
    Task<int> task2 = Task.Run(() => LongRunningOperationAsync());
    Task<int> task3 = Task.Run(() => LongRunningOperationAsync());

    // 等待所有任务完成
    await Task.WhenAll(task1, task2, task3);

    // 可以继续处理任务结果
    Console.WriteLine("所有任务已完成");
}

*Task 支持取消异步操作,这可以通过 CancellationToken 实现。

await MyMethodWithCancellationAsync();
//返回操作已被取消(是由异常输出的)
static async Task<int> LongRunningOperationWithCancellationAsync(CancellationToken cancellationToken)
{
    await Task.Delay(1000, cancellationToken);
    return 42;
}

static async Task MyMethodWithCancellationAsync()
{
    using (var cts = new CancellationTokenSource())
    {
        Task<int> task = Task.Run(() => LongRunningOperationWithCancellationAsync(cts.Token));

        // 模拟超时逻辑,实际使用时可能基于其他条件
        cts.CancelAfter(500); // 500毫秒后取消任务

        try
        {
            int result = await task;
            Console.WriteLine($"操作结果: {result}");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("操作已被取消");
        }
    }
}

在使用 Task 时,错误处理也是一个重要的方面。

await HandleTaskAsync();
//返回:发生错误: 操作失败
//注意:操作失败 是通过异常抛出的,后的语句进行了捕获
//我通常很少这样操作
static async Task<int> OperationThatMayFailAsync()
{
    // 模拟可能失败的操作
    await Task.Delay(100);
    throw new InvalidOperationException("操作失败");
}

static async Task HandleTaskAsync()
{
    try
    {
        await Task.Run(() => OperationThatMayFailAsync());
    }
    catch (Exception ex)
    {
        Console.WriteLine($"发生错误: {ex.Message}");
    }
}