为什么Thread.Join()在UI线程上调用时挂起我的应用程序?

时间:2017-04-13 21:19:01

标签: c# multithreading

根据这个问题的答案Why Thread.Join() DOES NOT hang my application when called on UI thread? thread.Join如果从STA线程调用它不应该挂起UI。我使用了与链接问题相同的代码

    private void button1_Click(object sender, EventArgs e)
    {
        string retValue = "";
        Thread thread = new Thread(
        () =>
        {
            retValue = LongRunningHeavyFunction();
        });
        thread.Start();
        thread.Join();
        button1.Text = retValue;
    }

    private string LongRunningHeavyFunction()
    {
        Thread.Sleep(5000);
        return "Done";
    }

方法主要在类Program中标记为[STAThread]。但是,当我按下按钮UI被冻结,我不能拖动窗口等我很困惑。我错过了什么吗?在我的情况下,为什么UI会被冻结?

2 个答案:

答案 0 :(得分:0)

.always(...)会导致UI冻结。

如果您想在Thread.Sleep中等待一段时间,请使用计时器对象。

这是一个例子,如何使用计时器:

How to use a timer to wait?

答案 1 :(得分:0)

thread.Join()告诉当前线程等待thread。在这种情况下,当前线程是GUI线程,您告诉它等待工作线程。因此,在工作线程完成之前,您的GUI线程不执行任何操作。由于GUI线程什么都不做,它不处理正常的GUI活动,导致冻结。

解决方案是不阻止您的GUI。相反,运行长时间运行的进程,无需等待它,这样您的GUI线程就可以继续响应用户。然后,一旦长时间运行的进程完成,使用GUI调度程序回调以设置结果。

代码可能如下所示:

private void button1_Click(object sender, EventArgs e)
{
    Thread thread = new Thread(
    () =>
    {
        //  Perform work
        var retValue = LongRunningHeavyFunction();

        //  Call the GUI thread
        button1.Dispatcher.BeginInvoke(() =>
        {
            //  .Dispatcher called the GUI thread.
            //  This code happens back in the GUI thread once the
            //  worker thread has completed.

            button1.Text = retValue;
        });
    });
    thread.Start();
}

private string LongRunningHeavyFunction()
{
    Thread.Sleep(5000);
    return "Done";
}