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

如何让异步Action在ExecuteActivityAsync中完整同步执行?

问题解决思路及代码修改方案

问题根源

你当前代码的核心问题是使用了async void委托(将异步lambda赋值给Action类型)。async void属于异步编程中的“火并忘记”模式,Task.Run无法跟踪其完整的异步执行流程——当执行到第一个await时,Task.Run就会认为任务已完成,触发后续的ContinueWith逻辑,而实际后续的异步方法还在后台执行,这就导致了"Completed"提前输出。

修改方案

  1. 将委托类型从Action改为Func<Task>,这样异步lambda会返回Task,其完整的异步执行流程可以被正确跟踪。
  2. 调整ExecuteActivityAsync方法的参数类型,并移除ContinueWith,直接await异步委托的执行结果,确保所有异步步骤完成后再输出"Completed"。

修改后代码

Test方法修改

public async Task Test()
{
    CancellationToken cancellationToken = default;

    // 替换Action为Func<Task>,让异步lambda返回可跟踪的Task
    Func<Task> taction = async () =>
    {
        this.Insert();
        await this.Method1();
        await this.Method2();
        await this.Method3();
        await this.SaveChangesAsync(cancellationToken);
    };

    await this.ExecuteActivityAsync(taction);
}

ExecuteActivityAsync方法修改

private async Task ExecuteActivityAsync(Func<Task> act)
{
    await semaphore.WaitAsync();
    try
    {
        Console.WriteLine("StartExecution");

        // 直接await异步委托,确保所有步骤执行完成
        await act();

        Console.WriteLine("Completed");
        Console.WriteLine("EndExecution");

        await Task.Delay(10000);
    }
    finally
    {
        semaphore.Release();
    }
}

若需保留Task.Run执行(可选)

如果需要将委托放在后台线程执行,可修改为如下形式:

private async Task ExecuteActivityAsync(Func<Task> act)
{
    await semaphore.WaitAsync();
    try
    {
        Console.WriteLine("StartExecution");

        // 用Task.Run包装后await,确保后台线程的异步流程完成
        await Task.Run(act);

        Console.WriteLine("Completed");
        Console.WriteLine("EndExecution");

        await Task.Delay(10000);
    }
    finally
    {
        semaphore.Release();
    }
}

修改后,控制台输出将完全符合你的预期顺序。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:00:01