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

标签 c# asynchronous async-await task deadlock

有没有办法同步等待在同一线程上运行的异步方法?

想要的效果是

  • 让 Worker() 在 UI 线程上异步运行
  • 同时在 Close() 方法返回之前等待它完成

下面的示例进入死锁,如果我使 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?

您不需要同步等待。通过使用 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
}

我缺少 Close() 的实现,但我怀疑您可以不使用它并中继表单关闭事件来取消工作人员。

关于c# - 同步等待异步方法在同一线程上完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29453337/

相关文章:

c# - 私有(private) Azure 云服务?

c# - 调用异步函数的不同方式

javascript - 在 NodeJS 中需要一个异步函数

c# - 类、结构或接口(interface)成员声明中的无效标记 'return'

C# 持续监视正在重新创建的文件

multithreading - Spring Integration 的异步发布订阅是如何工作的?

javascript - Node.js:REST 客户端在返回之前返回值

javascript - 如何用async/await获取第二个 `then`回调参数?

javascript - Promise 中的 JS Promise

c# - 呈现应该为正数的负数的阶乘计算器。怎么修?