如何在多线程或基于 wcf 服务的应用程序中正确使用事件?

Posted

技术标签:

【中文标题】如何在多线程或基于 wcf 服务的应用程序中正确使用事件?【英文标题】:How can i use events properly in multi-thread or wcf service-based applications? 【发布时间】:2016-08-18 12:14:39 【问题描述】:

我有提供一些实时事件的设备,制造商给了我一个 dll 用于使用该事件并基于该设备开发程序。 这是该 dll 的一些属性和事件:

    [ClassInterface(0)]
[ComSourceInterfaces("zkemkeeper._IZKEMEvents")]
[Guid("00853A19-BD51-419B-9269-2DABE57EB61F")]
[TypeLibType(2)]
public class CZKEMClass : IZKEM, CZKEM, _IZKEMEvents_Event

    public CZKEMClass();

    [DispId(79)]
    public virtual int AccGroup  get; set; 
    [DispId(76)]
    public virtual int BASE64  get; set; 
    [DispId(2)]
    public virtual int CommPort  get; set; 
    [DispId(64)]
    public virtual int ConvertBIG5  get; set; 
    [DispId(123)]
    public virtual int MachineNumber  get; set; 
    [DispId(78)]
    public virtual uint PIN2  get; set; 
    [DispId(102)]
    public virtual int PINWidth  get; 
    [DispId(241)]
    public virtual int PullMode  get; set; 
    [DispId(1)]
    public virtual bool ReadMark  get; set; 
    [DispId(191)]
    public virtual int s-s-rPin  get; 

    public virtual event _IZKEMEvents_OnAlarmEventHandler OnAlarm;
    public virtual event _IZKEMEvents_OnAttTransactionEventHandler OnAttTransaction;
    public virtual event _IZKEMEvents_OnAttTransactionExEventHandler OnAttTransactionEx;
    public virtual event _IZKEMEvents_OnConnectedEventHandler OnConnected;
    public virtual event _IZKEMEvents_OnDeleteTemplateEventHandler OnDeleteTemplate;
    public virtual event _IZKEMEvents_OnDisConnectedEventHandler OnDisConnected;
    public virtual event _IZKEMEvents_OnDoorEventHandler OnDoor;
    public virtual event _IZKEMEvents_OnEMDataEventHandler OnEMData;
    public virtual event _IZKEMEvents_OnEmptyCardEventHandler OnEmptyCard;
    public virtual event _IZKEMEvents_OnEnrollFingerEventHandler OnEnrollFinger;
    public virtual event _IZKEMEvents_OnEnrollFingerExEventHandler OnEnrollFingerEx;
    public virtual event _IZKEMEvents_OnFingerEventHandler OnFinger;
    public virtual event _IZKEMEvents_OnFingerFeatureEventHandler OnFingerFeature;
    public virtual event _IZKEMEvents_OnHIDNumEventHandler OnHIDNum;
    public virtual event _IZKEMEvents_OnKeyPressEventHandler OnKeyPress;
    public virtual event _IZKEMEvents_OnNewUserEventHandler OnNewUser;
    public virtual event _IZKEMEvents_OnVerifyEventHandler OnVerify;
    public virtual event _IZKEMEvents_OnWriteCardEventHandler OnWriteCard;

他们给了我一个这样的实时事件的示例代码:

if (this.RegEvent(this.iNo, 65535))//Here you can register the realtime events that you want to be triggered(the parameters 65535 means registering all)
        
            _zkemkeeper.OnFinger += new zkemkeeper._IZKEMEvents_OnFingerEventHandler(axCZKEM1_OnFinger);
            _zkemkeeper.OnVerify += new zkemkeeper._IZKEMEvents_OnVerifyEventHandler(axCZKEM1_OnVerify);
            _zkemkeeper.OnAttTransactionEx += new zkemkeeper._IZKEMEvents_OnAttTransactionExEventHandler(axCZKEM1_OnAttTransactionEx);
            _zkemkeeper.OnFingerFeature += new zkemkeeper._IZKEMEvents_OnFingerFeatureEventHandler(axCZKEM1_OnFingerFeature);
            _zkemkeeper.OnEnrollFingerEx += new zkemkeeper._IZKEMEvents_OnEnrollFingerExEventHandler(axCZKEM1_OnEnrollFingerEx);
            _zkemkeeper.OnDeleteTemplate += new zkemkeeper._IZKEMEvents_OnDeleteTemplateEventHandler(axCZKEM1_OnDeleteTemplate);
            _zkemkeeper.OnNewUser += new zkemkeeper._IZKEMEvents_OnNewUserEventHandler(axCZKEM1_OnNewUser);
            _zkemkeeper.OnHIDNum += new zkemkeeper._IZKEMEvents_OnHIDNumEventHandler(axCZKEM1_OnHIDNum);
            _zkemkeeper.OnAlarm += new zkemkeeper._IZKEMEvents_OnAlarmEventHandler(axCZKEM1_OnAlarm);
            _zkemkeeper.OnDoor += new zkemkeeper._IZKEMEvents_OnDoorEventHandler(axCZKEM1_OnDoor);
            _zkemkeeper.OnWriteCard += new zkemkeeper._IZKEMEvents_OnWriteCardEventHandler(axCZKEM1_OnWriteCard);
            _zkemkeeper.OnEmptyCard += new zkemkeeper._IZKEMEvents_OnEmptyCardEventHandler(axCZKEM1_OnEmptyCard);
            _zkemkeeper.m_bRegisteredEvents = true;
            uLog("Ends");
        

我可以在我的单线程或 Windows 应用程序中使用此示例,它可以正常工作并正确触发实时事件,但是当我在多线程应用程序或服务层(如基本 wcf 服务)中使用它时不工作! 请帮帮我

【问题讨论】:

【参考方案1】:

在 STA 线程内创建

Thread createComAndMessagePumpThread = new Thread(() =>

    //you code here
);
createComAndMessagePumpThread.SetApartmentState(ApartmentState.STA);
createComAndMessagePumpThread.Start();

【讨论】:

【参考方案2】:

什么不起作用?

通常会在 IO 线程上提供实时更新。对于 Windows 应用程序,如果您希望与 UI 线程仿射元素交互,则必须将调用编组到 UI 线程上。

【讨论】:

我想触发实时事件,但它们不能正常工作。【参考方案3】:

这样调用事件将不起作用,因为在线程内引发的事件只会触发该特定线程中的订阅者。您需要使用可以向其他线程发出信号的事件。

我建议通读微软网站上的这个问题板:https://social.msdn.microsoft.com/Forums/en-US/13f30e33-7f61-498e-a91a-ef982a63453c/event-handling-in-multithreaded-apps?forum=netfxbcl

答案提供了详细信息以及如何创建可以有效地向其他线程发出信号的事件。

【讨论】:

感谢您的帮助,但我无法编辑提供这些事件的 dll 代码 @HamidSOS 我想我不明白你的意思。您不需要编辑任何额外的 .dll 文件来实现跨线程事件。你到底想编辑什么,在什么 .dll 中? 我不需要编辑那个 dll,我只需要在多线程或 wcf 应用程序中正确使用这些实时事件 我也读过这个问答***.com/questions/6185610/… 啊...我现在知道我误读了您最初的陈述。我对那种级别的操作了解不多,无法在这里为您提供很多帮助。对不起!

以上是关于如何在多线程或基于 wcf 服务的应用程序中正确使用事件?的主要内容,如果未能解决你的问题,请参考以下文章

在多线程应用程序中使用 mongodb 的正确方法

如何强制 WCF 线程中未处理的异常使进程崩溃?

WCF 服务和线程

在JAVA中ArrayList如何保证线程安全

Boost asio程序在多线程上崩溃

如何在多线程程序中传递或共享开放流引用?