2010-07-20 50 views
0

我有一种情况,我希望主线程在等待,而其他线程可以在主线程上调用,而无需调用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"; 
    } 
} 

谢谢

回答

1

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

一些在.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(); 

} 
+0

感谢您的示例。我很好奇其他人如何接近启动画面问题。我猜测最终最好是尽快释放Main(UI)线程,以便其他线程可以通过invoke()与UI进行交互。 – dsum 2010-07-22 04:55:26

+0

没问题。如果这回答了您的问题,则应通过单击复选标记将其标记为已回答。 – Josh 2010-07-28 02:35:21

+0

仅供参考:C#5.0 CTP将有新的语法调用“async”和“await”,这正是我正在寻找的解决上述问题的方法。希望它会使我的代码更具可读性,而不是具有所有这些回调。 – dsum 2010-11-22 19:31:49

1

号,需要调用Application.Run,然后计划在UI线程上的代表。

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

+0

我不知道有一个任务类。我倾向于依靠使用Thread,ThreadPool或调用。谢谢(你的)信息。 我希望Main()代码执行“出现”线性运行,这将使代码审查更易于遵循。这会在应用程序初始化时隐藏一些复杂性。 – dsum 2010-07-22 04:27:57

相关问题