Search code examples
c#dispatcherautoreseteventwaitone

C# AutoResetEvent WaitOne stopped by dispatcher


private void WaitForDriveToBecomeReady()
{
    AutoResetEvent syncEvent = new AutoResetEvent(false); //set wait signal to use later

    //dispatcher to be able to change stuff in xaml from within thread
    Action action1 = new Action(delegate() { grdMain.Children.Add(notification); });
    Action action2 = new Action(delegate() { grdMain.Children.Remove(notification); });
    Thread restoreThread1 = new Thread(()=>{
        grdMain.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, action1); //show a notification

        Thread.Sleep(1500); //sleep a bit...

        grdMain.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, action2); //hide a notification

        syncEvent.Set(); //signal to continue at *.WaitOne()
    });
    restoreThread1.Start();

    syncEvent.WaitOne(); //let main thread wait until *.Set(); is called
}

The above code works perfect IF you comment out the two grdMain.Dispatcher.Invoke(...);. It also works perfekt if you comment out the *.Set(); and *.WaitOne(); But WHYYYY? I need both ^^. I don't get it...


Solution

  • I finally had time to continue read more about async and await. Thanks @Jacob for pointing out what was the problem.

    Here is my working async code for a toast notification that appears as long as you don't connect your drive.

    //the method
    public async Task WaitForDriveAsync(string path, string waitingToastText)
    {
        int width = 300;
        int height = 125;
        TextBlock toastTextBlock = new TextBlock() { Text = waitingToastText, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, FontSize = 23, Width = (width - 15), TextWrapping = TextWrapping.WrapWithOverflow };
        Grid notification = new Grid();
        notification.Width = width;
        notification.Height = height;
        notification.Background = Brushes.Red;
        notification.Margin = new System.Windows.Thickness(0, 27, 0.4, 0);
        notification.VerticalAlignment = VerticalAlignment.Top;
        notification.HorizontalAlignment = HorizontalAlignment.Right;
        notification.Children.Add(toastTextBlock);
    
        grdMain.Children.Add(notification);
    
        while (!Directory.Exists(path))
        {
            await Task.Delay(1000);
        }
    
        grdMain.Children.Remove(notification);
    }
    
    //to call it
    private async void btnBackupNow_Click(object sender, RoutedEventArgs e)
    {
        await WaitForDriveAsync(@"B:\", "Please connect your drive.");
    }