0

我有这个代表:

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 表单上的按钮的单击事件上运行。

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

这是怎么回事,为什么我的方法不是异步运行的?

4

3 回答 3

3

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

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

Task.Factory.StartNew(() => InstantiateForm(imageToPassIn));
于 2013-01-16T14:35:44.047 回答
1

Dispatcher.Invoke将动作放入队列中以在 UI 线程上执行。如果您希望执行冗长的计算,您可能应该在工作线程中执行此操作,从而让 UI 线程可以自由地做其他事情。例如,您可以尝试ThreadPool.QueueUserWorkItem.

于 2013-01-16T14:35:43.907 回答
0

问题是构造一个新的Window仍然需要调度器来完成工作,所以如果你的构造器Window需要很长时间来执行,调度器仍然会等待该构造器完成,尽管之前已经调用Invoke过。

您想要做的是使您的构造函数非常快,然后创建一个可用于设置图像的属性,并使该属性以异步方式完成所有冗长的工作,这样 UI 线程就不会被占用。

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

于 2013-01-16T14:38:32.810 回答