【发布时间】:2015-07-10 22:17:00
【问题描述】:
我有一个基本类,用于显示带有异步延迟的淡入(和淡出)通知,以尝试保持 UI 响应。
public partial class Notification : Form
{
public Notification(string message)
{
InitializeComponent();
txtNotification.Text = message;
}
async new public void Show()
{
FadeIn();
await Task.Delay(7000);
FadeOut();
}
async void FadeIn()
{
Opacity = 0;
base.Show();
while (Opacity < 1.0)
{
await Task.Delay(50);
Opacity += 0.05;
}
Opacity = 1;
}
async void FadeOut()
{
while (Opacity > 0.0)
{
await Task.Delay(50);
Opacity -= 0.05;
}
Opacity = 0;
Hide();
}
}
我还有一个 UI 事件处理程序想要执行一些繁重的工作,然后显示通知。
async public void MyHandler(args)
{
await Task.Run(() =>
{
System.Diagnostics.Debug.WriteLine("Do something!");
});
new Notification("Work completed!").Show();
}
我在通知 FadeIn 'await Task.Delay(50)' 期间遇到了死锁。我是这个 async await malarkey 的新手,但据我了解,我不能简单地 ConfigureAwait,因为我需要在 UI 线程上淡入通知,并且我正在使用 async 并等待“一直向下”。如果我只是删除事件处理程序中完成工作的行,那么就没有死锁,但我正在等待它完成,所以不明白为什么我会陷入死锁。我肯定在这里误解了什么?
根据要求,我现在删除了 async void 并减少了代码:
public partial class Notification : Form
{
public Notification()
{
InitializeComponent();
}
async Task FadeIn()
{
Opacity = 0;
base.Show();
while (Opacity < 1.0)
{
await Task.Delay(50);
Opacity += 0.05;
}
}
}
我发现该问题不会在 WinForm 应用程序中重现,但会按照 Outlook 插件中的说明重现。为了更加简单,我现在使用 AddIn StartUp 事件,以下代码显示通知没有问题
async private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
await new Notification().FadeIn();
}
但是正如我之前描述的那样,这段代码会导致挂起/死锁
async private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
await Task.Run(() =>
{
System.Diagnostics.Debug.WriteLine("Do something!");
});
await new Notification().FadeIn();
}
我新建了一个AddIn,没有其他代码,所以我认为问题一定是Outlook。(?)
【问题讨论】:
-
这里没有任何东西可以导致死锁。这真的是你正在运行的吗?
-
你可能不应该这样做
async void FadeOut()。请改用async Task FadeOut()。 -
@YuvalItzchakov 这与我正在运行的非常接近。通知类是准确的。该处理程序是一个功能区 xml 控件处理程序。也许这不是死锁,但执行在“等待 Task.Delay(50);”处无限期结束/挂起在 FadeIn 中,除非我立即删除 'new Notification("Work completed!").Show();' 之前的行。
-
1) 避免使用
async void。 2) 请发布一个最小的、可重现的示例。 -
@RussellHorwood:尝试将其添加为
ThisAddIn_Startup的第一行:SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
标签: c# multithreading asynchronous async-await