DateTime相等和声明导致ContextSwitchDeadlock

时间:2012-01-27 14:35:20

标签: c# datetime declaration

我认为这是一个愚蠢的问题,但我发现我无法做到以下情况有点奇怪:

EditingItem.FROM = EditingItem.TO = DateTime.Now;   // FROM, TO are DateTime   

在这次操作之后,程序有时挂起,但有时它只是按照我的想法运作。
这是一个例外:

  

检测到ContextSwitchDeadlock消息:CLR无法执行   从COM上下文0x478b80转换到COM上下文0x478dd0为60   秒。拥有目标上下文/公寓的线程是   最有可能是做非抽水等待或处理很长时间   运行操作而不抽取Windows消息。这个情况   通常会对性能产生负面影响甚至可能导致   应用程序变得无响应或内存使用累积   随着时间的推移。为避免这个问题,所有单线程   公寓(STA)线程应该使用抽取等待原语(例如   CoWaitForMultipleHandles)并且在很长时间内定期泵送消息   正在运行。

将代码更改为:

  EditingItem.FROM = DateTime.Now;
  EditingItem.TO = DateTime.Now;

在我的情况下有所帮助。

不能正确地搜索问题,看看解释,那么你能帮助解释为什么表达错误吗? PS在评论中更多讨论。 以下是一些实验结果:

DateTime d = DateTime.Now;
EditingItem.FROM = EditingItem.TO = d;//hang

为时间添加循环:

for (int i = 0; i < 100000; i++)
{
   i++;
}

DateTime d = DateTime.Now;
EditingItem.FROM = EditingItem.TO = d;//hang

2 个答案:

答案 0 :(得分:2)

您的代码等同于以下内容:

var temp = DateTime.Now;
EditingItem.TO = temp;
EditingItem.FROM = temp;

将分配放在一行只是一个简写,可能显示C#的C语言根。

现在您已经提供了有关您的问题的更多信息,似乎您的程序由于COM死锁而挂起。很难看到DateTime值的赋值可以强制死锁。异常表明CLR正在尝试调用未处理消息泵的STA(单线程单元)中的COM对象。

我只是想描述一个可能的情况,但是我知道你的问题的具体细节我可能会离开:

让我们假设您的用户界面中有一个基于COM的控件来响应事件(例如点击)。在事件处理程序中,启动后台线程,然后事件处理程序等待该线程完成或设置后台任务完成的信号。后台任务(在另一个线程上运行)然后尝试获取COM对象上的属性。这将触发您遇到的死锁。

在COM控件之外的另一个公寓中运行的后台线程必须编组对COM控件(STA)的公寓的调用。这是通过向COM使用的隐藏窗口发送Windows消息来完成的。但是,当前阻止调度该Windows消息的线程等待后台线程完成。后台线程正在等待用户界面线程调度Windows消息。这是一个僵局。

要避免这种情况,请不要阻止用户界面线程,或者如果您必须至少确保在等待时泵送消息泵。如何完成这一点在异常消息中暗示。

答案 1 :(得分:2)

你的问题是似乎发生了lock - 再次没有提供代码只是猜测 - 对象被锁定,以便从另一个属性分配属性将自行死锁。

如果您正在处理COM,可以通过COM对象是Single-Threaded Apartment对象来实现这一点。