编辑:我的不好,没有暴力事件的行为。错误是代码中的其他地方。感谢大家的帮助。请忽略此问题
请有人向我解释这里发生了什么。我遇到了意外的事件行为。
有一个单身人士课程:
internal class QueueListener
{
private static readonly object QueueChangeLock = new object();
private readonly List<IQueuedJobExecutioner> jobsQueue = new List<IQueuedJobExecutioner>();
// Here comes singleton private constructor, Instance property, all classic.
// Important line in constructor is this:
QueueManager.NewJobQueued += NewJobQueuedHandler;
private void NewJobQueuedHandler(object sender, NewJobQueuedEventArgs args)
{
lock (QueueChangeLock)
{
// This is the problematic place, note this!
jobsQueue.Add(args.QueuedJobExecutioner);
}
}
}
现在有第二堂课:
public class QueueManager
{
public static event NewJobQueuedEventHandler NewJobQueued;
protected void RaiseNewJobQueuedEvent(IQueuedJobExecutioner queuedJobExecutioner)
{
if (NewJobQueued != null)
{
NewJobQueued(this, new NewJobQueuedEventArgs { QueuedJobExecutioner = queuedJobExecutioner });
}
}
}
两个类都驻留在服务器上。通过WCF调用客户端执行new QueueManager().MyMethod()
,调用RaiseNewJobQueuedEvent
。
一切正常,但如果几乎同时发出两个事件,我会在调试器中看到有问题的地方(请参阅QueueListener中的注释):
不判断设计本身(它有一些“历史”原因),为什么会发生这种情况?这种预期的行为和事件是否在某种程度上得到了jobsQueue的快照,或者这是无意义的,我只是错过了一些难题的部分?
编辑: 我会说它是一个单例,并且是这样实现的(原始帖子中省略了这些行):
class QueueListener
{
private static readonly object SyncRoot = new object();
private QueueListener()
{
//...
}
public static QueueListener Instance
{
get
{
if (instance == null)
{
lock (SyncRoot)
{
if (instance == null)
{
instance = new QueueListener();
}
}
}
return instance;
}
}
}
答案 0 :(得分:0)
Yuval是正确的,你的班级不是单身人士。当您使用公共静态方法创建实例和私有构造函数时,将创建单例。私有构造函数确保创建实例的唯一方法是通过公共方法。
有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/ff650316.aspx。
答案 1 :(得分:0)
你的QueueListener
课程实际上不是单身人士。这对您来说意味着您正在创建它的多个实例。要解决此问题,您必须在类声明中添加static
关键字,并声明static
构造函数。尝试将您的课程更改为如下所示:
internal static class QueueListener
{
private static readonly object QueueChangeLock = new object();
private static readonly List<IQueuedJobExecutioner> jobsQueue = new List<IQueuedJobExecutioner>();
// This is the singleton constructor that will be called
static QueueListener()
{
// Here comes singleton private constructor, Instance property, all classic.
// Important line in constructor is this:
QueueManager.NewJobQueued += NewJobQueuedHandler;
}
// Rest of class code...
}