【发布时间】:2012-07-25 22:23:32
【问题描述】:
在下面的代码中,我有两个类,一个在单独的线程中运行并触发事件,另一个订阅此事件并从事件接收数据。我基于 Jon Skeet 的文章 http://csharpindepth.com/Articles/Chapter2/Events.aspx 的事件代码
在这篇文章http://www.codeproject.com/Articles/37474/Threadsafe-Events 中它说...
出于这个原因,我推荐 Jon Skeet 在 Delegates and Events 最后推荐的相同方法:“不要那样做”,即不要以多线程方式使用事件。如果对象上存在事件,那么只有一个线程应该能够订阅或取消订阅该事件,并且将引发该事件的线程是同一线程。
现在显然我的设计打破了这一点,因为它在与它订阅的线程不同的线程上触发事件。我怎样才能修改我的设计,使其符合不以多线程方式使用事件的原则,或者这是不可能的?
我想到的另一种方法是将我的回调方法作为委托传递给 B 类并调用它而不是调用事件?
我可能有完全错误的一端,所以任何澄清将不胜感激。
注意:我知道 .Net 4.0 显然已经解决了这个问题,但是如果有办法在 .Net 4 之前解决这个问题,我仍然很感兴趣
public delegate void MyDelegate(int a);
class A
{
void main()
{
B bObject = new B();
bObject.MyEvent += new MyDelegate(NiceMethod);
bObject.Run();
}
void NiceMethod(int a)
{
Console.Writeline({0}, a);
}
}
class B
{
readonly object eventLock = new object();
MyDelegate myDel;
public event MyDelegate MyEvent
{
add
{
lock (eventLock)
{
myDel += value;
}
}
remove
{
lock (eventLock)
{
myDel -= value;
}
}
}
//Assume this runs in a new thread and calls back data using MyEvent
//Have ommited thread code for simplicity
public void Run()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
MyDelegate handler;
lock (someEventLock)
{
handler = myDel;
}
if (handler != null)
{
handler (i);
}
}
}
}
【问题讨论】:
-
c# 编译器总是为类似字段的事件(即编译器为您编写添加/删除的地方)添加了线程安全性 - 对此的实现已得到改进在 c# 4 中。此外,这不是 .net 4 的东西 - 它是 ac# 4 的东西 :)
-
@MarcGravell 感谢您提供信息!
标签: c# multithreading events