2012-05-25 142 views
2

WPF控件我有一个异步运行Task,当它完成这样的触发事件。但是当我尝试这样做时,会导致一个异常:The calling thread must be STA, because many UI components require this。调用方法InitializeComponent()时,类构造函数中发生异常。创建从一个单独的线程

据我所知,通常acessing WPF从单独threades控制使用Dispatcher.Invoke处理,它总是为我工作,所以我试了一下:

Dispatcher.Invoke(new Action(() => 
{ 
    InitializeComponent(); 
})); 

但在这种情况下异常不断发生的历史。 那么任何人都可以告诉如何从一个单独的线程创建一个WPF控件的实例吗? 或者,也许这将是一个更好的方法来将主题UI线程完成事件,如果是的话,我该怎么做?

任何帮助表示赞赏。谢谢。

回答

3

您必须使用与UI线程关联的Dispatcher实例。如果你写的东西是这样的:在任务体

Dispatcher.Invoke(new Action(() => 
{ 
    InitializeComponent(); 
})); 

,您使用的是调用线程,这可以从池中后台线程的调度。

无论如何,有了任务,你不应该直接使用Dispatcher。使用适当的任务调度程序:

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
Task.Factory.ContinueWhenAll(tasks.ToArray(), 
    result => 
    { 
     // put you UI calls here 

    }, CancellationToken.None, TaskContinuationOptions.None, ui); 

其中tasks是任务的顺序来使用默认调度执行。

+0

这似乎上班,谢谢! – Slippy

1

我已经在过去

Dispatcher.Invoke(DispatcherPriority.Normal, 
        new Action(
         delegate() 
         { 
          //access control created by main thread 
          textBlock.Text = msg; 
         } 
         )); 
+0

因为我们正在创建一个'Control',所以我会使用DispatcherPriority.Render。 – Guillaume

+0

我已经能够添加控制到父母这种方式至少... EX:panel.Children.Add(新的MyControl())等 – TGH

+0

谢谢,但'Dispatcher.Priority'在我的情况下没有改变( – Slippy

1

从另一个线程调用构造函数在InitializeComponent这样做似乎是自找麻烦。该对象还没有(我们在构造函数中)

将其回收到UI线程通常会做到这一点,但在构造函数期间对我来说看起来像个坏主意。

如果要异步初始化控件,只需订阅加载的事件,以便知道该对象在那里,生成一个执行一些计算/数据检索的线程并将数据编组回到UI线程以显示它。