C#在没有Application.DoEvents的情况下使用EndInvoke完全运行异步方法

时间:2017-10-11 13:23:27

标签: c# async-await invoke

我遇到了以下代码的问题:

private int check = 1;

private async System.Threading.Tasks.Task AsyncMethod()
{
    check = 2;
    await ...;
    check = 3;
}

private void Load(object sender, EventArgs e)
{
    var invoke = this.BeginInvoke(async x =>
    {
        await AsyncMethod();
    });
    Debug.WriteLine("1: " + check);
    EndInvoke(invoke);
    Debug.WriteLine("2: " + check);
    Application.DoEvents();
    Debug.WriteLine("3: " + check);
}

每当我运行AsyncMethod时,我想立即完全结束EndInvoke。但是,它返回:

1: 1
2: 2
3: 3

而我希望它返回2: 3。有没有办法在没有Application.DoEvents的情况下执行此操作(因为我希望尽可能避免使用它)?

编辑:经过进一步测试,似乎Application.DoEvents在这种情况下效果最好。它甚至可以在AsyncMethod包含多个await来电时使用;所有这些都是在Application.DoEvents后运行EndInvoke时运行的。

1 个答案:

答案 0 :(得分:0)

您要找的是取消,取消只能在.NET中合作完成。

Microsoft的文档中的

Here is a article解释了使您的任务/线程可取消的过程。但是短版本是你需要传递给函数CancellationToken并在整个方法中检查它以取消代码。

private int check = 1;

private async Task AsyncMethod(CancellationToken token)
{
    check = 2;
    await Task.Delay(5000, token); //Wait for 5 seconds or till the token is signaled.
    token.ThrowIfCancellationRequested();
    check = 3;
}

//Event handlers like this is the only place you are allowed to do async void
private async void Load(object sender, EventArgs e)
{
    Debug.WriteLine("1: " + check);
    try
    {
        var cts = new CancellationTokenSource();
        var task = AsyncMethod(cts.Token); //Start the task
        cts.Cancel();
        await task; //Wait for the task to finish or throw a OperationCanceledException
        Debug.WriteLine("2: " + check);
    }
    catch(OperationCanceledException)
    {
        //Do nothing
    }
    Debug.WriteLine("3: " + check);
}

以上将输出

1: 1
3: 2