是否可以在等待的线程上调用?

时间:2010-07-20 03:28:48

标签: .net multithreading

我有一种情况,我希望主线程等待,而其他线程可以在主线程上调用,而无需调用Application.Run。

以下代码显示了我尝试实现的内容,但主线程和数据加载线程导致死锁。

    static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        var form1 = new Form1();
        form1.Show();

        Thread loadDataThread = new Thread(() =>
        {
            //Load Data that takes a long time
            string title = LoadData();
            form1.Invoke((Action)delegate { form1.Text = title; });
        });

        loadDataThread.Name = "Data Loading Thread";
        loadDataThread.Start();

        //wait for loading to be completed (deadlock)
        loadDataThread.Join();

        //Do more stuffs

        Application.Run();
    }

    private static string LoadData()
    {
        Thread.Sleep(1000);
        return "Hello Thread";
    }
}

谢谢

2 个答案:

答案 0 :(得分:1)

没有。您需要调用Application.Run,然后在UI线程上安排委托。

P.S。最好使用Task类而不是Control.Invoke

答案 1 :(得分:1)

调用只能起作用,因为在Windows窗体应用程序中,有一个消息循环在应用程序的整个生命周期内运行。如果在Thread.Join上被阻止,则消息循环不处理消息,这也意味着它不处理您的Invoke调用。

在.NET框架中有一些阻塞调用可以提取消息,但是你不能(也不应该)依赖这些,因为它们往往会产生重新入侵的错误。你的申请很难解决。

在等待数据加载时,不要阻止UI线程,而应该让它在后台运行,并显示启动画面。然后在最后,您可以使用BeginInvoke关闭启动屏幕并打开主屏幕或在加载结束时需要执行的任何操作。有点像...

static void Main() {

    Application.EnableVisualStyles();

    var splashScreen = new Form1();
    var mainScreen = new Form2();

    splashScreen.Show();

    ThreadPool.QueueUserWorkItem(delegate {

        LoadLotsOfData();

        splashScreen.BeginInvoke(delegate {
            splashScreen.Close();
            mainScreen.Show();
        });

    }

    Application.Run();

}