简体   繁体   English

同步等待异步方法在同一线程上完成

[英]Wait synchronously for an async method to finish on the same thread

Is there a way to wait synchronously for an async method that runs on the same thread? 有没有一种方法可以同步等待在同一线程上运行的异步方法?

The desired effect is 理想的效果是

  • to have the Worker() run asynchronously on the UI thread 使Worker()在UI线程上异步运行
  • and at the same time wait for it to finish before the Close() method returns 并同时等待它完成,然后Close()方法返回

The example below enters in a deadlock, and if I make Form1_FormClosing() async I don't satisfy the second condition. 下面的示例进入死锁,并且如果我使Form1_FormClosing()异步,则我不满足第二个条件。

public partial class Form1 : Form
{
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    CancellationTokenSource cts = new CancellationTokenSource();
    public Form1()
    {
        InitializeComponent();
        Show();
        Worker(cts.Token); // async worker started on UI thread
    }

    async void Worker(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
            await TaskEx.Delay(1000);
        tcs.SetResult(true); // signal completition
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Close();
        MessageBox.Show("This is supposed to be second");
    }

    private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        cts.Cancel(); // request cancel 
        tcs.Task.Wait(); // deadlock
        await tcs.Task; // button1_Click() gets control back instead of Worker()
        MessageBox.Show("This is supposed to be first");
    }
}

Is there a way to wait synchronously for an async method that runs on the same thread? 有没有一种方法可以同步等待在同一线程上运行的异步方法?

You don't need to synchronously wait. 您无需同步等待。 By making Worker async Task instead of async void you can get the desired behavior and remove the useless TaskCompletionSource : 通过使Worker async Task而不是async void您可以获得所需的行为并删除无用的TaskCompletionSource

private Task workerTask;
public Form()
{
     workerTask = Worker(cts.Token);
}

private async Task Worker(CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
        await TaskEx.Delay(1000);
}

private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    cts.Cancel(); // request cancel
    await workerTask; // Wait for worker to finish before closing
}

I'm missing the implementation of Close() , but i suspect you could do without it and relay on the form closing event to cancel the worker. 我缺少Close()的实现,但是我怀疑您可以不用它,而是通过Close()表单事件来取消工作程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM