有没有办法同步等待在同一个线程上运行的异步方法?
期望的效果是
以下示例进入死锁状态,如果我使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");
}
}
答案 0 :(得分:3)
有没有办法同步等待在同一个线程上运行的异步方法?
您无需同步等待。通过制作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()
的实现,但我怀疑你可以不使用它并在表格结束事件中转发以取消工作人员。