Why is Task.Wait() causing application to freeze

2019-09-26 04:55发布

问题:

When I call BuildCustomer.StartTask, I then call a method WriteToDatabase. Inside WriteToDatabase, I want to send a status back to the MainForm to write the status to the GUI. When the code reaches that point, my application freezes up and gives no error. I did find out that if I remove task.Wait(), it stops freezing and works. But I think I want the wait in because my BuildCustomer takes a bit of time and writes a lot of updates (including more updates from Common class) to the GUI. Can someone tell me what is wrong or what I should be doing differently? This is a .Net 4 project so I cannot use async, which I've seen other answers for.

public partial class MainForm : Window
{
    public MainForm()
    {
        Common.SendMessage += UpdateStatus;
    }

    private void Button_Click(object sender, EventArgs e)
    {
        BuildCustomer.StartTask();
    }

    private void UpdateStatus(string message)
    {
        Dispatcher.Invoke(new Action(() =>
        {
            StatusTextBox.Text = message;
        }));
    }
}

public class BuildCustomer
{
    public static void StartTask()
    {
        var action = new Action<object>(BuildCustomer);

        var task = new Task(() => action(buildDetails));

        task.Start();

        task.Wait();
    }

    private void BuildCustomerDetails(object buildDetails)
    {
        Common.WriteToDatabase();
    }
}

public class Common
{
    public delegate void MessageLogDelegate(string message);

    public static event MessageLogDelegate SendMessage;

    public static void WriteToDatabase()
    {
        SendMessage("Some status message to write back to the GUI");
    }
}

回答1:

You have a deadlock. The StartTask waits on task.Wait() to complete but this occurs (is called on) on the calling thread which is the main UI thread.

The Task being waited eventually reaches UpdateStatus which calls an Invoke on the UI thread as well but this thread is currently waiting on task.Wait() (so it is blocking which results in the UI thread not being available indefinitely).



回答2:

Try to add async keyword to method signature and use this:

await task;

It cause to does not sleep main thread(UI thread).