回到我以前的非托管 C++ 时代,我可以信任多线程应用程序中的关键部分。所以,现在使用 dotNet/C#,我在锁定机制上进行中继。通过锁定资源,我确信任何线程都无法在我的代码段中访问这些资源。
这在 dotNet 中似乎不是真的!
我有我的 Windows 服务应用程序。我创建了一个主托管线程,其中包含一个托管第三方 OCX 的隐藏表单。在这个线程中,我对对象列表进行消息抽查。此对象列表被此托管线程中的 OCX 触发的事件修改。
我在这里发布了我的代码的简化部分:
public bool Start()
{
ServiceIsRunning = true;
m_TaskThread = new Thread(new ParameterizedThreadStart(TaskLoop));
m_TaskThread.SetApartmentState(ApartmentState.STA);
m_TaskThread.Start(this);
return true;
}
private void OnOCXEvent(object objToAdd)
{
lock(m_ObjectList)
{
m_ObjectList.Add(objToAdd); }
}
}
private void CheckList()
{
lock(m_ObjectList)
{
foreach(object obj in m_ObjectList)
{
...
}
}
}
[STAThread] // OCX requirement!
private void TaskLoop(object startParam)
{
try {
...
while (ServiceIsRunning)
{
// Message pump
Application.DoEvents();
if (checkTimeout.IsElapsed(true))
{
CheckList();
}
// Relax process CPU time!
Thread.Sleep(10);
}
} catch(Exception ex) {
...
}
}
你不会相信我:我在 CheckList 中有一个“列表已被修改”异常!8-/
所以我做了一些日志记录,我注意到当SAME托管线程位于 CheckList foreach 循环中时,将引发 OnOCXEvent。我确定:我的日志文件中有相同的托管线程 ID,foreach 循环尚未完成,并且 OnOCXEvent 已由同一个托管线程调用!
现在我想知道:这怎么会发生?单个托管线程是否使用更多 win32 线程实现?
希望有人能解释为什么会这样,所以我可以解决这个问题。
谢谢,法比奥
我的笔记:
我实际上解决了在 foreach 循环之前创建列表副本的问题。但我不喜欢这个解决方案。我也想了解正在发生的事情。我不拥有第三奇偶校验 OCX 代码,但我在 CheckList 循环中调用的方法在逻辑上与被触发的 OCX 事件无关。