在Dispatcher.Invoke调用期间,WPF UI是非强制性的

时间:2013-01-16 14:31:25

标签: .net wpf multithreading dispatcher

我有这个代表:

private delegate void NoArgDelegate(BitmapImage image);

我实例化委托并使用Dispatcher.Invoke运行它,如下所示:

var fetcher =  new NoArgDelegate(InstantiateForm);
Dispatcher.Invoke(fetcher, DispatcherPriority.Normal, imageToPassIn);

我有一个私有字段在任何方法范围之外,但在我的ViewModel范围内,在InstantiateForm中我实例化对象:

private OmrForm _ormForm;

private void InstantiateForm(BitmapImage image)
{
    _ormForm = new OmrForm(image);
}

这一切都发生在我的ViewModel中的一个方法中,该方法在我的WPF表单上的按钮的click事件上运行。

我在构造函数中做了一些工作来计算我传入的图像类型并适当地设置坐标,大约2秒,我希望我的UI在这段时间内能够响应,但事实并非如此。我尝试过使用BeginInvoke也无济于事。

这里发生了什么,为什么我的方法不是异步运行的?

3 个答案:

答案 0 :(得分:3)

在Window或UserControl中调用Dispatcher.Invoke将在UI线程上运行该代码,因为控件的Dispatcher设置为在UI线程上工作。

你想要的是开始一个后台线程。这可以使用Task类来实现。

Task.Factory.StartNew(() => InstantiateForm(imageToPassIn));

答案 1 :(得分:1)

Dispatcher.Invoke将一个操作放在队列中以在UI线程上执行。如果你想进行冗长的计算,你应该在一个工作线程中这样做,这样就可以让UI线程自由地做其他事情了。例如,您可以尝试ThreadPool.QueueUserWorkItem

答案 2 :(得分:0)

问题是构造一个新的Window仍然需要调度程序才能工作,所以如果你的Window的构造函数需要很长时间才能执行,那么Dispatcher仍然会等待构造函数完成,尽管之前已调用Invoke

你想要做的是让你的构造函数非常快,然后创建一个可用于设置图像的属性,并使该属性以同步方式完成所有冗长的工作,因此UI线程不是捆绑。

有些人建议使用线程来调用你的方法,但是在另一个线程上创建一个新的Window并不是一个好主意,还有其他含义。