我有一个基本类,用于显示通过异步延迟淡入(和退出)的通知,以保持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)'时遇到了死锁。我是新手这个异步等待malarkey,但据我所知,我不能简单地使用ConfigureAwait,因为我需要淡化UI线程上的通知,我正在使用异步并等待“一直向下”。如果我只是删除执行工作的事件处理程序中的行,那么就没有死锁,但我正在等待它完成,所以无法理解为什么我最终陷入死锁。当然我在这里误解了什么?
根据要求,我现在删除了异步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中的描述进行重现。为了增加简单性,我现在使用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。(?)
答案 0 :(得分:0)
@StephenCleary提供了解决方案。在违规代码之前添加以下行。
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());