Winforms等待async / await任务永远不会返回

时间:2017-01-25 21:16:09

标签: c# winforms async-await

我有一个Winforms exe,从菜单中我启动一个运行缓慢的过程作为任务。获取数据然后显示对话框大约需要30秒。通常它不再返回。我捕获异常,日志中没有任何内容,所以我知道它运行正常。表单永远不会出现,似乎没有CPU时间占用。然而,我在调试器中运行它并逐步执行代码,它工作正常。偶尔它似乎可以在更快的PC上运行。怎么了?

    private async void inPlayRecordToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (!GetClient()) return;
        {
            await Task.Run(() =>
            {
                LaunchForm();
            });
        }
    }

    private async void LaunchForm()
    {
        try
        {
            {
                var inPlayView = new InPlayView();
                await inPlayView.GetData();
                inPlayView.ShowDialog();
            }
        }
        catch (Exception ex)
        {
            Logger.LogMessage(ex.ToString());
        }
    }

2 个答案:

答案 0 :(得分:1)

请改为:

private async void inPlayRecordToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (!GetClient()) return;

    await LaunchForm();
}

private async Task LaunchForm()
{
    try
    {
        var inPlayView = new InPlayView();
        await inPlayView.GetData();
        inPlayView.ShowDialog();
    }
    catch (Exception ex)
    {
        Logger.LogMessage(ex.ToString());
    }
}

您不希望Task.Run()用于已经异步的方法,并且作为一般规则,async void对于事件处理程序是可以的,因此不是{{1方法。

同样正如评论指出的那样,LaunchForm()将任务排队到ThreadPool,因此它将最终脱离UI线程。

答案 1 :(得分:0)

我在我的一个项目中使用了异步/等待,我无法想出在任务中执行ShowDialog的原因。不确定这是否有效,但您可能想稍微改变一下流量。这应该使它更加一致并且可能更容易调试。

private async void inPlayRecordToolStripMenuItem_Click(object sender, EventArgs e) {
    if (!GetClient()) {
        return;
    }

    var playView = await LaunchForm();

    if (playView != null) {
        playView.ShowDialog();
    }
}

private async Task<InPlayView> LaunchForm() {
    try {
        var inPlayView = new InPlayView();
        await inPlayView.GetData();

        return inPlayView;
    } catch (Exception ex) {
        // do cleanup of view if needed
        Logger.LogMessage(ex.ToString());
        return null;
    }
}