繁体   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