在后台线程中创建元素然后添加到主界面

我在WPF中遇到线程问题。 我想创建一个复杂的用户界面,然后我想将它添加到我的主窗口。 虽然这个复杂的用户界面正在创建,但我希望在主窗口中显示进度条。 我认为这只能通过线程来实现。 但有一个问题。 创建的元素无法添加到主窗口,因为它是在单独的线程中创建的。 有人知道是否有可能将在后台线程中创建的UIElements转移到主线程。 如果我以一种简单的方式尝试,它表示无法访问该对象,因为它位于一个单独的线程中。 我已经使我的进度条线程安全了。

我希望以下示例更好地解释我想要的内容。

StackPanel tcForm = new StackPanel(); Semaphore loadedSema = new Semaphore(0,1); Thread thread = new Thread(new ThreadStart(delegate(){ //Formular should be created in background tcForm.Children.Add(new Formular()); ProgressBar.AddProgress(); //...other things loadedSema.Release(); })); thread.start(); loadedSema.WaitOne(); 

new Formular()运行了很长时间,所以我想在后台创建。

Formular添加到变量然后添加主线程也是不可能的。

 //this is also impossible //in background-thread form = new Formular //in main-thread tcForm.Children.Add(form); 

我希望有办法解决这个问题。 如果有一些建议会很好,

谢谢,马丁

您应该使用Dispatcher.Invoke方法

 ... this.Dispatcher.Invoke(delegate{ tcForm.Children.Add(new Formular()); ProgressBar.AddProgress();};) .... 

编辑
如果调度很长,可以在调度之前创建Fromular()对象

 var f = new Formular(); this.Dispatcher.Invoke(delegate{ tcForm.Children.Add(f); ProgressBar.AddProgress();};) 

我对WPF了解不多,但我刚刚了解了BackGroundWorker,它可以为你完成这项工作。

http://dotnetperls.com/backgroundworker

您只需处理在任务之后引发的WorkerCompleted事件,并且应该在主线程中运行。 它还可以报告更新进度条的进度。

例:

  void worker_Start() { BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.RunWorkerAsync("MyArg"); } void worker_DoWork(object sender, DoWorkEventArgs e) { e.Result = new Formular(); } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { this.Controls.Add((Control)e.Result); } 

如果您要做的只是更新进度条(或类似),那么您应该在主线程中预先创建所有UI,然后使用表单的Invoke方法将后台线程的状态更新发送到主线程(例如,发送一个int表示0到100%之间的进度)

我不认为有一种方法可以在线程之间共享Windows窗体控件。

编辑:好的,我现在看到这是标记为WPF。 答案保持不变,但不是在控件上调用,而是使用Dispatcher类(每个图形元素都包含对正确调度程序的引用)。 您还可以使用另一个答案中建议的BackgroundWorker类。

不 – 那是不可能的。 WPF主要是单线程的。

但是,您应该想知道为什么界面的创建需要花费很多时间。 WPF非常快。 “普通”控制创造不应成为瓶颈。

也许你可以优化其他对象创作; 尝试分析您的应用程序。

并尝试从下到上构建您的UI:最后一项操作应该是将控件添加到表单中。

您可以XAML序列化您的ui元素,然后将它们发送回主线程。 不确定在主线程中反序列化是否比在第一个位置创建它们更快。