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

C#异步启动窗体后Task.Result未等待完成的代码修复咨询

问题修复方案

核心问题分析

  1. 拼写错误:代码中sampleTask.Reslt是笔误,正确应为sampleTask.Result,但更关键的是直接调用Result会阻塞UI线程,违背你避免卡顿的需求,还存在线程死锁风险。
  2. sampleAsync实现逻辑错误:你用Task.Factory.StartNew开启后台线程后,立刻通过BeginInvoke切回UI线程显示模态窗体,但BeginInvoke是异步调用,后台线程会直接结束,导致sampleTask提前完成,返回的是初始值true,而非窗体关闭后的实际结果。
  3. 不必要的线程切换:StartProcess本身是快速启动操作,不需要用Task.Run包裹,反而增加线程切换开销。

修复后的代码

1. 修正sampleAsync方法

直接在UI线程异步等待窗体关闭,无需额外后台线程:

public async Task<bool> sampleAsync()
{
    var anotherForm = new AnotherForm();
    anotherForm.main = this;
    // 通过TaskCompletionSource异步等待窗体关闭事件
    var tcs = new TaskCompletionSource<bool>();
    anotherForm.FormClosed += (s, e) =>
    {
        tcs.SetResult(anotherForm.rtn);
        anotherForm.Dispose();
    };
    anotherForm.Show();
    return await tcs.Task;
}

2. 修正Button_Click方法

用await替代Result,移除不必要的Task.Run,并修正Teams路径的语法错误:

private async void Button_Click(object sender, EventArgs e)
{
    Task<bool> sampleTask = sampleAsync();

    bool rtn = false;
    if (startOutlookCheckBox.Checked)
    {
        rtn = StartProcess(@"C:\Program Files (x86)\Microsoft Office\root\Office16\OUTLOOK.EXE", "");
        if (rtn)
        {
            await Task.Delay(10000); 
        }
    }

    if (startTeamsCheckBox.Checked)
    {
        // 修正路径拼接的语法错误
        string teamsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 
            @"Microsoft\Teams\Update.exe");
        rtn = StartProcess(teamsPath, "--processStart \"Teams.exe\"");
        if (rtn)
        {
            await Task.Delay(5000); 
        }
    }

    try
    {
        // 用await异步等待任务完成,不会阻塞UI
        bool taskResult = await sampleTask;
        if (taskResult)
        {
            a();
        }
        else
        {
            b();
        }
    }
    catch (Exception ex) // 异步方法抛出的异常直接捕获,无需AggregateException
    {
        Debug.WriteLine(ex.Message);  
        return;
    }
}

3. 修正StartProcess方法(补充变量声明)

private Process startApp; // 补充成员变量声明
private bool StartProcess(string exeFullPath, string param = "")
{
    try
    {
        if (File.Exists(exeFullPath))
        {
            startApp = string.IsNullOrEmpty(param) 
                ? Process.Start(exeFullPath) 
                : Process.Start(exeFullPath, param);
            return true;
        }
        else
        {
            return false;
        }
    }
    catch (Exception ex)
    {
        return false;
    }
}

关键说明

  • 用TaskCompletionSource监听窗体关闭事件,既实现异步等待窗体结果,又不会阻塞主UI线程,能正确获取窗体返回值。
  • 用await sampleTask替代Result,确保异步等待任务完成,避免UI卡顿和线程死锁。
  • 移除StartProcess外层的Task.Run,因为启动进程的操作本身不耗时,无需额外线程切换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:53:09