0

I know there are quite a lot of Post about Task deadlocks, but I simply can't find the right sollution.

So I basically have this setup:

public event EventHandler StateChangedEvent;
public bool Busy
{
    ...
    set
    {
        ...
        this.StateChangedEvent?.Invoke(this, EventArgs.Empty)
    }
}
public void Main()
{
    ...
    this.StateChangedEvent += this.OnStateChangedEvent;
}
public void OnStateChangedEvent(object sender, EventArgs e)
{
    this.TextBox.Invoke(() => this.TextBox.Text = "Change");
    this.Invoke(() => this.Cursor = Cursors.WaitCursor);
}
public void ButtonAction_Click(object sender, EventArgs e) //actually part of an API with an virtal - override method on between. Can't change here to async
{
    ...
    Task.Run(async () => await this.AsyncDoStuff()).Wait();
    ... // Synchron stuff needs to be done afterwards
}
public async Task AsyncDoStuff()
{
    this.Busy = true; //Causes Deadlock
    await Stuff1();
    await Stuff2();
}

So in reality those calls are split among different classes, but the basic structure remains. Yes I know I should go async all the way up, but let's say the first ButtonAction_Click is part op an API/Framework and can't be changed to async. I know the reason is because I block the UI Thread and then access it again...So what is the best solution for this?

Thanks in advance!

Robin
  • 123
  • 7

1 Answers1

0

So from your other comments it sounds like the code in ButtonAction_Click is outside your control and you can't change it. Unfortunately, that's where the problem is - this event handler is totally blocking the UI thread until the work has finished. There's no way to unblock the thread.

Your only recourse is to avoid any blocking interactions with the UI thread.

The following code from your example is definitely going to cause deadlock, because Invoke() will block until the UI (which is already blocked) responds:

this.TextBox.Invoke(() => this.TextBox.Text = "Change");
this.Invoke(() => this.Cursor = Cursors.WaitCursor);

You could try using BeginInvoke() instead of Invoke(), but the unfortunate consequence is that these UI changes won't actually execute until the UI thread is unblocked, and by then your background work is already finished. It might fix your deadlock, though.

RogerN
  • 3,761
  • 11
  • 18