C#为所有对象订阅相同事件处理程序是否线程安全 [英] C# Is it thread safe to subscribe Same event handler for all Objects

查看:145
本文介绍了C#为所有对象订阅相同事件处理程序是否线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目中有一种情况,我已连接到多个服务器并监听事件.每当从服务器收到事件时,处理程序都应将事件添加到公共队列中进行处理.所有连接都应将收到的事件添加到队列中.

foreach(var item in collection)
{
        Connection c = new connection(item);

         c.start();
         c.EventReceived+=new EventHandler(myHandler);
         list.add(c);
}

protected void  myHandler(eventArgs)
{
     //add it to the concurrent queue
}

我怀疑它是否能够处理那些事件而没有任何线程问题.如果您有任何模式或内置的API可以安全地处理此问题,请告诉我.

解决方案

线程安全始终需要一个上下文-一个来源.

如果您的意思是+ =

对于+=,这取决于事件的实现方式.如果将其实现为类似字段的事件,即

public event SomeEventType EventReceived;

然后是:它是线程安全的.该规范要求类似字段的事件的访问器是线程安全的,尽管实现可能会有所不同(例如,以前使用lock(this)lock(typeof(DeclaringType))的MS编译器,但是现在改为使用Interlocked). /p>

如果该事件是手动实施的,即

public event SomeEventType EventReceived {
    add { ... }
    remove { ... }
}

然后,线程安全性完全由add/remove实现定义.

如果您是指调用

这是线程安全的,因为委托是不可变的,但是请注意,所有这些都发生在调用该线程的单个线程上.但是,常见的错误是在null测试中引入了竞争条件:

if(EventReceived != null) EventReceived(this, someArgs);

上面的不是线程安全的,因为从技术上讲,EventReceived的值可以在测试后更改.为了确保这不会出错,应该为:

var handler = EventReceived;
if(handler != null) handler(this, someArgs);

如果您是说处理程序的话

然后,线程安全性完全由各个处理程序定义.例如,在UI应用程序中,处理程序必须检查并切换到UI线程.

I have a situation in my project where i have connect to multiple server and listen for events. Whenever a event received from the server, Handler should add the event to the common queue for processing. All connections should add received events to the queue.

foreach(var item in collection)
{
        Connection c = new connection(item);

         c.start();
         c.EventReceived+=new EventHandler(myHandler);
         list.add(c);
}

protected void  myHandler(eventArgs)
{
     //add it to the concurrent queue
}

Here i doubt that whether it can be able to handle those events without any threading issues. Please let me know if you have any patterns or built in APIs to handle this safely.

解决方案

Thread-safety always needs a context - a from what.

If you mean the +=

For the +=, that depends on how the event is implemented. If it is implemented as a field-like event, i.e.

public event SomeEventType EventReceived;

then yes: it is thread-safe. The specification requires that the accessors for field-like events are thread-safe, although the implementation can vary (for example, the MS compiler used to use lock(this) or lock(typeof(DeclaringType)), however it now uses Interlocked instead).

If the event is implemented manually, i.e.

public event SomeEventType EventReceived {
    add { ... }
    remove { ... }
}

Then the thread-safety is defined entirely by the add/remove implementations.

If you mean the invoke

Then that is thread-safe since delegates are immutable, but note that it all happens on the single thread that invokes the thread. However, a common mistake is to introduce a race condition in a null test:

if(EventReceived != null) EventReceived(this, someArgs);

The above is not thread-safe, since technically the value of EventReceived can change after the test. To ensure this does not error, it should be:

var handler = EventReceived;
if(handler != null) handler(this, someArgs);

If you mean the handlers

Then the thread-safety is defined entirely by the individual handlers. For example, in UI applications it is the handlers that must check for, and switch to, the UI thread.

这篇关于C#为所有对象订阅相同事件处理程序是否线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆