簡體   English   中英

從單獨的線程創建WPF控件

[英]Creating WPF control from a separate thread

我有一個異步運行的Task ,它在完成時會觸發一個事件,如下所示:

task.ContinueWith(() => {
    if (MyEvent != null)
        MyEvent(this, EventArgs.Empty);
}

然后,事件處理程序應創建WPF控件的實例。 但是,當我嘗試這樣做時,它會導致一個異常: The calling thread must be STA, because many UI components require this 調用方法InitializeComponent()時,類構造函數中發生異常。

據我所知,通常使用Dispatcher.Invoke處理從單獨的線程訪問WPF控件的過程,它始終對我有用,所以我嘗試了一下:

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

但是在那種情況下,異常不斷發生。 如何從單獨的線程創建WPF控件的實例?

也許這是將完成事件封送至主UI線程的更好方法。 如果是,我該怎么做?

您必須使用與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是使用默認調度程序執行的一系列任務。

我過去曾這樣做:

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

從構造函數在另一個線程上調用InitializeComponent似乎很麻煩。 該對象尚不存在(我們在構造函數中)

將其封送回UI線程通常可以解決問題,但是在構造函數期間,這對我來說似乎是個壞主意。

如果要異步初始化控件,只需訂閱已加載的事件,就可以知道該對象已存在,請生成一個線程進行一些計算/數據檢索,並將數據封送回UI線程以進行顯示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM