简体   繁体   English

异步等待UI死锁

[英]Async Await UI Deadlock

I have a basic class for showing notifications that fades in (and out) with asynchronous delays in an attempt to keep the UI responsive. 我有一个基本类,用于显示通过异步延迟淡入和淡出的通知,以使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();
    }
}

I also have a UI event handler that wants to perform some heavy lifting, then show a notification. 我也有一个UI事件处理程序,它想要执行一些繁重的工作,然后显示一个通知。

async public void MyHandler(args)
{
    await Task.Run(() => 
    {
            System.Diagnostics.Debug.WriteLine("Do something!");
    });
    new Notification("Work completed!").Show();
}

and I am running into deadlock during notification FadeIn 'await Task.Delay(50)'. 并且在通知FadeIn'await Task.Delay(50)'时遇到死锁。 I'm new to this async await malarkey but as I understand it I can't simply ConfigureAwait because I need to fade the notification in on the UI thread and I am using async and await 'all the way down' as it were. 我是异步await malarkey的新手,但据我了解,我不能简单地进行ConfigureAwait,因为我需要在UI线程上淡入通知,而我正在使用async并一直“一直”等待。 If I simply remove the line in the event handler that does the work then there is no deadlock, but I'm awaiting for it to complete so can't understand why I'm ending up in deadlock. 如果我只是简单地删除执行该工作的事件处理程序中的行,那么就没有死锁,但是我正在等待它完成,因此无法理解为什么我最终陷入死锁。 Surely I've misunderstood something here? 我肯定在这里误解了吗?

As requested I've now removed the async void's and reduced the code: 根据要求,我现在删除了异步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;
        }
    }
}

and I've discovered that the issue does not reproduce in a WinForm app, but does reproduce as described in an Outlook AddIn. 并且我发现该问题不会在WinForm应用程序中重现,但确实会按照Outlook AddIn中的描述重现。 For increased simplicity I'm now using the AddIn StartUp event and the following code shows the notification no problem 为了简化起见,我现在使用AddIn StartUp事件,以下代码显示通知没有问题

    async private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {            
        await new Notification().FadeIn();
    }

but this code causes hang/deadlock as I described previously 但是此代码会导致挂起/死锁,如我之前所述

    async private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        await Task.Run(() =>
       {
           System.Diagnostics.Debug.WriteLine("Do something!");
       });
        await new Notification().FadeIn();
    }

I've created a new AddIn, there is no other code, so I figure the problem must be Outlook.(?) 我创建了一个新的AddIn,没有其他代码,所以我认为问题一定是Outlook。(?)

@StephenCleary provided the solution. @StephenCleary提供了解决方案。 Add the following line before the offending code. 在有问题的代码之前添加以下行。

SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM