WPF应用程序中的背景和UI线程

时间:2010-09-22 00:17:49

标签: c# wpf mvvm

我正在阅读DataModel-View-ViewModel pattern: 2

我真的不明白需要检查我是否在UI或后台线程中。如果我跳过支票怎么办?另外,下面的代码......

[Conditional("Debug")]
protected void VerifyCalledOnUIThread()
{
    Debug.Assert(Dispatcher.CurrentDispatcher == this.Dispatcher,
        "Call must be made on UI thread.");
}

并没有真正做任何事情,例如。设定值。所以,如果我没有调试它会做任何事情吗?

3 个答案:

答案 0 :(得分:4)

  

我真的不明白需要检查我是否在UI或后台线程中。如果我跳过支票怎么办?

使用Dispatcher并检查您是否在UI或后台线程上的原因是因为WPF要求只能在创建它们的线程上访问控件。原因是因为控件不是线程安全的。如果您没有进行多线程处理(即所有代码都在主线程上),那么您不必担心这一点。 WinForms也有同样的限制。

如果您尝试从与其创建的线程不同的线程访问控件,您将获得InvalidOperationException

  

此外,下面的代码......并没有真正做任何事情,例如。设定值。所以,如果我没有调试它会做任何事情吗?

在编译发布版本时,Debug.Assert(以及您的VerifyCalledOnUIThread方法)甚至不会出现在代码中,所以不会发生任何事情。

答案 1 :(得分:2)

如果您正在使用其他线程,则只需要担心这一点。如果您没有明确地这样做,那么您可能正在使用UI线程。

在UI线程上处理某些异步操作回调,例如Web服务/ wcf调用。 此外,如果您使用计时器,例如DispatchTimer,它也在UI线程上。 最后,如果您使用BackgroundWorker线程,那么也会在UI线程上处理。

希望这有帮助。

答案 2 :(得分:2)

很抱歉,但我不同意Chris Schmich的观点。

您可以看到VerifyCalledOnUIThread()中显示DataModel。实际上,目的是 To Veryfy仅从UI线程访问的DataModel(不是控件)。是的WPF / SilverLight UI不是跨线程安全的,但在这种情况下,这不是真正的原因。

事实是,如果您将某些内容(datamodel / viewmodel)绑定到WPF / SilverLight UI,并且您从UI线程以外的其他线程访问它,那么您将获得无法提供信息的异常。无法解决此错误非常困难,因为Exception抛出并没有给出任何线索。

我举例说明:

//pass model to datacontex and bind it 
mycontrol.DataContext = myModel;

//myThreadedService is an assynchronous service
//done ini different thread.
//so ServiceDone will call myModel.Complete from different thread
//system will crash unexpectedly without enough clue
myThreadedService.ServiceDone += (s, e) => { myModel.Complete = true; }
myThreadedService.CallService();

所以,我想你现在明白为什么这段代码应该存在:

Debug.Assert(Dispatcher.CurrentDispatcher == this.Dispatcher,
        "Call must be made on UI thread.");

当您从不同的线程访问DataModel时,此代码将给出一个线索。