You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何并行运行两个返回Task的方法?代码同步运行问题排查与解决

问题分析与修正

错误点

  • 方法无真正并行逻辑:Method和Info都是同步方法,返回Task.CompletedTask只是形式上符合Task返回要求,但实际调用时会同步阻塞当前线程,不会在后台并行执行。Main方法中先调用Method会直接占满主线程,直到i递增到21亿才会执行Info,完全没有并行效果。
  • 共享变量线程不安全:两个方法同时读写变量i,没有任何同步机制,会引发竞态条件,导致读取的i值不准确(比如递增操作可能被CPU指令重排或中断,显示的数值不是最新的)。
  • 取消逻辑不合理:Main中先await task1,意味着要等Method执行完才会取消Info,不符合“并行运行直到手动终止”的需求。

修正方案

  1. 用Task.Run将两个方法委托给线程池线程执行,实现真正的并行。
  2. 使用Interlocked类处理共享变量i的递增和读取,保证线程安全。
  3. 调整Main中的等待逻辑,同时等待两个任务,支持通过Q键主动终止所有任务。

修正后的完整代码

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

class Program
{
    static void Method(ref int i, int target, CancellationToken cancellationToken)
    {
        while (Interlocked.CompareExchange(ref i, 0, 0) < target && !cancellationToken.IsCancellationRequested)
        {
            Interlocked.Increment(ref i);
        }
    }

    static void Info(ref int i, CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo keyInfo = Console.ReadKey(true);
                if (keyInfo.Key == ConsoleKey.I)
                {
                    Console.Clear();
                    Console.WriteLine($"当前i值:{Interlocked.CompareExchange(ref i, 0, 0)}");
                }
                else if (keyInfo.Key == ConsoleKey.Q)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }
            }
            Thread.Sleep(10); // 减少CPU空转消耗
        }
    }

    static async Task Main()
    {
        int i = 0;
        using var cts = new CancellationTokenSource();

        // 将两个方法放到线程池并行执行
        Task task1 = Task.Run(() => Method(ref i, 2100000000, cts.Token), cts.Token);
        Task task2 = Task.Run(() => Info(ref i, cts.Token), cts.Token);

        try
        {
            // 等待任意一个任务完成(要么Method执行完,要么用户按Q取消)
            await Task.WhenAny(task1, task2);
        }
        catch (OperationCanceledException)
        {
            // 捕获取消异常,无需额外处理
        }
        finally
        {
            cts.Cancel();
            await Task.WhenAll(task1, task2); // 确保两个任务都正常结束
        }

        Console.WriteLine("Готово");
        Console.ReadKey();
    }
}

关键说明

  • Task.Run:把同步方法包装到线程池线程,让两个任务在后台并行执行,主线程不会被阻塞。
  • Interlocked:通过原子操作保证i的递增和读取线程安全,避免竞态条件导致的数值错误。
  • Task.WhenAny:等待任意一个任务完成(要么Method执行完毕,要么用户按Q触发取消),然后统一终止所有任务并等待它们结束。
  • Thread.Sleep(10):降低Info方法的CPU占用,避免循环空转浪费资源。

内容的提问来源于stack exchange,提问作者mozay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:56:42