【发布时间】:2016-02-10 12:26:46
【问题描述】:
我在 WinForms 应用程序中有这种奇怪的行为。我从主窗体的 Form_Shown 事件处理程序中调用此任务。
Task.Run(() => WatchHistory(CancellationTokenSource.Token));
函数定义如下。 FinishedRequestItem 对象是一个 WinForms UI 控件。它在等待 Task.Delay 处死锁。我注意到,一旦创建 FinishedRequestItem 对象,就会创建一个新的同步上下文。这个上下文与主表单 UI 的上下文不同。
private async void WatchHistory(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var completedRequests = await processContext.ProcessRequests.ToListAsync(cancellationToken);
if (completedRequests.Any())
{
FinishedRequestItem entry = Program.Container.GetInstance<FinishedRequestItem>();
}
await Task.Delay(CurrentHistoryRefreshMilliseconds, cancellationToken);
}
}
但是,如果我使用如下所示的 Invoke 方法创建 UI 控件,它不会死锁。我很好奇为什么?由于任务未在 UI 上下文中运行,是什么阻止了 Task.Delay 在上述代码中恢复?
while (!cancellationToken.IsCancellationRequested)
{
var completedRequests = await processContext.ProcessRequests.ToListAsync(cancellationToken);
if (completedRequests.Any())
{
FinishedRequestItem entry = null;
this.Invoke((Action)delegate()
{
entry = Program.Container.GetInstance<FinishedRequestItem>();
});
}
await Task.Delay(CurrentHistoryRefreshMilliseconds, cancellationToken);
}
【问题讨论】:
-
您应该只在 UI 线程上创建 UI 控件。你也不应该是
async void,而是使用async Task。 -
我在更新的代码中使用异步任务,我知道它是一个更好的模式。然而问题依然存在。我认为这与 Task.Delay 试图在等待它的同一线程中恢复有关。
标签: c# winforms async-await