首页 > 解决方案 > WinForms 事件在异步等待中乱序执行

问题描述

WinForms 事件出现故障。我想我明白为什么,但我很好奇解决它的最佳方法。

在下面的(人为的)代码中,首先被调用,但是当达到然后被调用Load时它放弃了控制。一旦完成,终于可以完成。awaitShownShownLoad

private async void SomeForm_Load(object sender, EventArgs e)
{
    someLabel.Text = "Start Load";
    await SomeMethod();
    someLabel.Text = "Finish Load";
}

private void SomeForm_Shown(object sender, EventArgs e)
{
    someLabel.Text = "Shown";
}


private async Task SomeMethod()
{
    await Task.Delay(1).ConfigureAwait(false);
}

我需要确保在执行Load之前完成Shown

这是我目前的解决方案:


Task _isLoadedTask;

private async void SomeForm_Load(object sender, EventArgs e)
{
    var tcs = new TaskCompletionSource();
    _isLoadedTask = tcs.Task;

    someLabel.Text = "Start Load";
    await SomeMethod();
    someLabel.Text = "Finish Load";

    tcs.TrySetResult();
}

private async void SomeForm_Shown(object sender, EventArgs e)
{
    await _isLoadedTask;

    someLabel.Text = "Shown";
}

明显的缺点是我必须手动设置边界/依赖项。确保事件按顺序执行的最佳方法是什么?

标签: c#winformsasync-await

解决方案


在这种情况下,覆盖OnLoad或订阅Load具有相同的效果。

但是,订阅Load会导致委托实例化和调用以及覆盖OnLoad不会也将更多地控制将要执行的内容和顺序。

尝试这个:

private Task isLoadedTask;

protected override void OnLoad(EventArgs e)
{
    this.isLoadedTask = OnLoadAsync();

    base.OnLoad(e);
}

private async Task LoadAsync()
{
    someLabel.Text = "Start Load";
    await SomeMethod();
    someLabel.Text = "Finish Load";
}

protected override async void OnShown(EventArgs e)
{
    base.OnShown(e);

    await _isLoadedTask;

    someLabel.Text = "Shown";
}

推荐阅读