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

C# 为什么Thread.Join()在UI线程上调用时会挂起我的应用程序?,c#,multithreading,C#,Multithreading,根据这个问题的答案,如果从STA线程调用,Join不应该挂起UI。我使用了和问题中相同的代码 private void button1_Click(object sender, EventArgs e) { string retValue = ""; Thread thread = new Thread( () => { retValue = LongRunningHeavyFuncti

根据这个问题的答案,如果从STA线程调用,Join不应该挂起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";
    }

类程序中标记为[StatThread]的Main方法。但当我按下按钮时,UI被冻结,我无法拖动窗口等。我很困惑。我错过什么了吗?为什么在我的情况下UI被冻结?

线程。睡眠导致UI冻结

如果要在
LongRunningHeavyFunction()
中等待一段时间,请使用计时器对象

下面是一个如何使用计时器的示例:

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";
}

它挂起是因为您正在阻止UI线程5秒钟。您说过“工作人员A应该雇用工作人员B,让他睡五年;工作人员A应该什么都不做,直到工作人员B再次醒来”;worker A——UI线程——什么都不做,这并不奇怪。更新用户界面并不是什么问题。现在,事实证明工人A确实做了一点工作,但不是很多。这还不够,你应该依赖它。你所做的是对[StatThread]合同的严重违反。CLR执行一些泵送操作以避免死锁,但只发送通知的一个子集。不是用户输入,因此拖动窗口无法工作。或者点击按钮,注意会导致DoEvents()风格的非常严重的重新进入问题。永远不要这样做。谢谢,我只是误解了这个问题。我认为用户界面是完全响应的,我想知道它是如何响应的,为什么在我的情况下它是错误的,不知道为什么这个问题得到了这么多的反对票。询问者需要知道的只是回调调度程序,而不是使用线程连接。容易解决。