多线程COMObject和UI线程(C#)这是我在这里的第一篇文章,实际上我通常使用你可以在这里找到的很棒的帖子数据库来解决我所有的问题。但我现在被困住了:我正在做一个遵循MVVM的项目,包括一个COM对象。正如我在研究期间读到的那样,我了解到COM对象只能从创建它的线程访问。我的COM对象实现了以下接口interfaceIComUpdate{voidUpdate();所以当我创建我的COM对象时,每次有更新(我不知道什么时候,它是随机的),COM服务器都会调用我实现COM对象类的Update()。我的目标是创建一个不同的线程,命名为COM对象线程,其中COM对象独立于我的UI线程存在,因此每次有更新时,我都会在与UI线程不同的线程中处理它。实际上它是有效的:在我的ViewModel开始时,我创建了一个特定对象的集合。这个对象,我们称之为ModelObj,是模型的一部分,它定义了一个静态构造函数。除了初始化一些变量外,应用程序还为COM对象创建并启动一个新线程:Threadt=newSystem.Threading。Thread(()=>{System.Threading.Thread.CurrentThread.Name="COM对象的线程";IComUpdatemyComObj;myComObj=(IComUpdate)Activator.CreateInstance(blabla);Application.Run();});吨。设置公寓状态(公寓状态.STA);t.开始();它实际上工作得很好,在我的COM对象的Update()实现中,我实际上看到线程是刚刚创建的线程,而不是UI线程。现在的问题是:我创建的ModelObj实现了INotifyPropertyChanged接口。我的想法如下:每次COM对象收到更新时,我处理来自COM对象线程的数据,并从该线程更新我的ModelObj实例的一些属性,因此这些属性将触发我的ModelObj和UI的属性更改thread用户界面将被更新。如果UI更新花费太多时间,我可能会错过屏幕上出现的一些Update(),但COM对象会将它们记录在我的ModelObj实例中,因此UI捕获所有更新并不重要,我只是不希望COM对象必须等待UI更新后才能再次调用它。我读了很多帖子,认为我的RaisePropertyChanged("property")会失败。实际上,即使在COM对象的线程中,RaisePropertyChanged也会成功执行,因此跟踪我的代码,我看到它切换到我的ViewModel程序集//这里我仍然在我的COM对象的线程中!base.NotifyOfPropertyChange(()=>this.property)之后是UI更新。注意:我正在使用CaliburnMicro在我的WPF视图和我的ViewModel之间进行绑定。所以我无法跟踪这个base.NotifyOfPropertyChange(()=>this.property)。也许Caliburn处理线程切换,那不是我的问题。我只能说我的COM对象线程在我的RaisePropertyChanged("property")之后等待UI更新以获取下一条指令,因此它与UI线程执行整个操作完全相同。我希望我的COM对象线程更新我的ModelObj,它将向UI发送一条消息进行更新(因为此ModelObj的某些字段已更改)并立即继续,而不知道UI是否实际更新。有没有人知道这种行为?非常感谢。####更新####谢谢大家的快速回答。我确实像ZdeslavVojkovic所说的那样:您应该始终从GUI线程更新GUI为了完整起见,我是这样做的:因为我的视图是完整的WPF,没有任何代码,所以我没有任何控件或表单来调用BeginInvoke,所以在我的ModelObj的静态构造函数中,我从UI线程构建了一个不可见的控件,以便能够对其调用BeginInvoke。所以我声明:publicstaticControlmInvokeControl;委托voidMyDelegate();私人我的委托_NotifyDelegate;然后在我对象的静态构造函数中执行此操作:mInvokeControl=newControl();mInvokeControl.CreateControl();在函数内部,我以这种方式初始化委托:_NotifyDelegate=newMyDelegate(this.NotifyByInvoke);然后我像这样使用它:ModelObj.mInvokeControl.BeginInvoke(this._NotifyDelegate);方法是:publicvoidNotifyByInvoke(){RaisePropertyChanged("Update");一切正常!COMObj只能从创建它的线程访问是不正确的。它取决于对象的单元模型,但通常您可以从任何线程访问它,并且它将在同一线程上调用或编组到正确的线程。我相信你的问题是你正在从后台线程更新GUI,这是一个主要的禁忌。您应该始终从GUI线程更新GUI。当您更新模型对象时,它仍然会在后台线程上发生,并且INotifyPropertyChanged接口的事件将在该线程上触发。您需要将模型更新同步到GUI线程(WinForms,而不是WPF-在WPF中,您应该使用frm.Dispatcher.BeginInvoke,但问题是一样的),方法如下:privatedelegatevoidExecuteActionHandler(Actionaction);publicstaticvoidExecuteOnUiThread(thisFormform,Actionaction){if(form.InvokeRequired){//我们不在UI线程上//Invoke或BeginInvoke,这取决于你需要什么//但是你说'并立即继续'所以BeginInvoke是form.BeginInvoke(newExecuteActionHandler(ExecuteOnUiThread),action);}else{//我们在UI线程上所以只执行动作action();还有一个类似问题的问题,我在其中提供了更多详细信息。我不知道你处理了多少数据,或者做GUI部分需要多长时间。您还可以考虑使用锁定队列。您可以使用ModelObj中的队列对新任务进行排队。这就是你得到的。然后你可能有一个计时器线程(在GUI线程上)。如果您有一些新数据要显示在GUI上,您只需在此处检查锁定的队列。您可以在本地使完整列表出列。然后你也可以检查一个组件上是否显示了多个数据。这样,您可以跳过已经有较新更新的更新。你跳过调用gui线程来做事。您可以一次执行多个GUI更新。如果您有太多事情要做,您可能只会将一定数量的项目出列,以便GUI对用户交互做出反应。但是,您需要检查队列是否没有增长。以上就是C#学习教程:MultiThreadingCOMObjectandUIthread(C#)分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
