检测到 ContextSwitchDeadlock异常(可能是程序死循环引起的)

1.问题

最近在做一个C#项目的时候(程序是读取文件然后插入数据库),程序遇到这么一个错误,最初以为是程序发生了死锁,或者以为数据库的哪个表被锁了,查了半天程序和数据库也没解决。。

2.于是看了很多解决方法,都说是用以下这个方法解决

但是这个解决方法只是治标不治本,只是不显示那个Error的弹窗,程序还是走不下去。。

3.最后看到这个博主的博客后,发现是程序在读取文件的时候发生了死循环

(1)问题背景

        最近在做一个反应速度测试软件,是用C#写的,刚开始是觉得是个小工具,随便做做就可以了,结果是越做越复杂,本来打算一到两个星期就可以做完的,结果是做了两个月,当然这期间还有其他事情在做的。

(2)问题出现

        在软件中需要一个功能,就是随机生成一个长度为120的数字序列,要求是:

1. 每个数字都是1、2、3、4这四个数中的一个;

2. 前后两个数不能重复;

3. 每个数(1、2、3、4)各30个,一共120个。

        我自己写了个算法,具体思路是这样的:循环120次,每次随机产生个数,然后判断这个数已经生成了多少次了,如果超过了30个或者跟前个数字重复,就重新随机产生。

进入调试之后,每次到循环这里,貌似都是循环到80次左右的时候就会出现ContextSwitchDeadlock异常,然而有时候又不会的。

        郁闷一个星期…

(3)问题解决

        我查了很多资料,网上很多关于这个异常的都是说怎么会关闭掉,只要在VS里面,“调试”“异常”“Managed Debugging Assistant”下,将这个异常的勾去掉就不会再出现了。

出现是不出现了,但问题是程序到这里下不去了,屏蔽掉也没有用。

在MSDN里面,对这个异常的解释是:


        如果在试图进行 COM 上下文转换期间检测到一个死锁,则将激活 ContextSwitchDeadlock 托管调试助手 (MDA)

(4)症状

        最常见的症状是:从托管代码对非托管 COM 组件的调用未返回任何结果。另一个症状是内存使用量与时俱增。

(5)原因

        原因很可能是单线程单元 (STA) 线程不发送消息。STA 线程或者等待而且不发送消息,或者执行一个长时间的操作而且不允许发送消息队列。

内存使用与时俱增的原因是:终结器线程试图对非托管 COM 组件调用 release 而该组件未返回任何结果。这会阻止终结器回收其他对象。

(6)解决办法

        遵循有关 STA 消息发送的 COM 规则。

对运行库的影响

        此 MDA  CLR 无任何影响。它只报告有关 COM 上下文的数据。

(7)输出

        一条描述当前上下文和目标上下文的消息。


        还查了些其他的资料,得出的结论是.NET下 强制转换需要很大的性能(因为才我的程序里面,得到的数字序列还要转换为枚举类型),所以造成溢出呀什么的,以为没的救了,就放弃了,跟“客户”商量了一 下,用别的办法了。但是后来又要求这个一定要实现了,就请教了一位老师,他看完我的算法后知道了是我的算法问题,具体描述一下:当我生成了119个数字之后,比如123都已经30个,这样最后一个数字只能是4了,然而如果倒数第二个数字正好也是4的话,这里就会出现死循环了。后来经过调试,发现果然是这个原因,原来不是死锁,而是死循环。哎…!惨败啊!

        所以,这里得出的另一个结论是,造成ContextSwitchDeadlock异常的又一原因是死循环。简简单单的原因,MSDN解释的这么复杂(对我而言),不过也有可能是MS没有把这个写出来,也就是MSDN的解释和死循环根本没关系。

        总之,希望这个对大家有所帮助吧,下面也贴一下老师帮我写另一个算法。仅供参考。

private static int[] Randomlist()
{
	Random ro = new Random();
	int[] Resultlist = new int[120];
	int[] KeyNumber = new int[4];
	int i,j,r,s,flg;
	for(i=0;i<120;i++)
	{  
	 Resultlist[i]=0;
	}

	for (i = 0; i < 4; i++)
	{
	 KeyNumber[i] = 0;
	}

	for (i = 0; i < 30; i++)
	{

	 for (j = 0; j < 4; )
	  {
		 r = (int)ro.Next(4);
		 flg = 1;
		 if (j > 0)
		  {
			 for (s = j-1; s >= 0; s--)
			  {
				 if (r== (KeyNumber[s]-1))
					 flg = 0;
			 }
		 }
		 if (flg == 1)
		  {
			 KeyNumber[j] = r + 1;
			 Resultlist[i * 4 + j] = KeyNumber[j];
			 j++;
		 }
	 }

	}

	for ( i=1;i<120;i++)
	{
	 if (Resultlist[i - 1] == Resultlist[i])
	  {
		 for(j=i+1;j<120;j++)
			 if (Resultlist[j] != Resultlist[i]) break;
		 if(j<120)
		  {
			 r = Resultlist[i];
			 Resultlist[i] = Resultlist[j];
			 Resultlist[j] = r;
		 }

	 }
	}

	for ( i = 119; i > 1; i--)
	{
	 if (Resultlist[i] == Resultlist[i - 1])
	  {
		 for ( j = i - 2; j >= 0; j--)
			 if (Resultlist[j] != Resultlist[i - 1]) break;
		 if (j >= 0)
		  {
			 r = Resultlist[i - 1];
			 Resultlist[i - 1] = Resultlist[j];
			 Resultlist[j] = r;
		 }
	 }
	}

	return Resultlist;
}

原文地址:https://www.cnblogs.com/adaiye/archive/2007/10/03/913282.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值