我想好像我的那个优化工具似乎也用不了这么长的时间啊,实际上有好几个需要进行代码分析地方速度都会有点慢,是不是代码分析器的分析速度的问题呢?由于速度实在太慢了,而且测试的范围太庞大了,我已经没有心思手动写expected应该是什么的代码了,放弃。可是我还是实在不甘心啊,怎么能不试一下这个功能呢?于是还是想测试一下DemoCharacter这个类,结果发现没有这个类——我忘了abstract的类是不能够测试的,可是如果我非要测试其中一些功能怎么办?百思不得其解,难道非要通过派生类测试?那如果我有一个abstract的BaseX派生出ChildA、ChildB、……、ChildZ,Children.Calc()根据BaseX.Calc()的计算结果来进行不同的计算,那么怎么测试BaseX.Calc()是否正确呢?难道要派生一个BlankChild来测试?那如果这样的问题比较多是不是太不好玩了,也许我的想法太特殊了。
OK,回归正题。原来的.Game Framework的代码在VS2k3的时候好好的,没有warning,跑到Whidbey下面却出现了一大堆的warning。仔细一看,原来说的是Thread.Suspend和Resume已经obsoleted,建议使用Threading下面的其他东西来进行同步,例如Monitor、ManualResetEvent等等来进行线程间的同步。Oops! 这可怎么好?我还是比较讨厌有warning的,先看看这个到底是怎么回事,为什么要废弃这种用法呢?
查了一下Whidbey的MSDN,原来说因为suspend的时候无法控制代码在什么地方被停止,也许正在等待一个SecurityPermission,或者在等待某个资源,或者在……,因此很容易引起死锁。打个比方吧:线程A已经占用了资源1,正在wait资源2,但是资源2被线程B占用了。线程B占用着资源2的同时,也在等待资源1,但是等着等着不耐烦了,他决定做点其他的事情,比如说把线程A挂起来,然后继续等待资源1。本来A等得不耐烦的时候就会释放资源1,可是这样的事情就会被B给彻底阻止了。
但是我的问题似乎还比较不好解决,如果不使用Suspend/Resume的话。因为我正好需要“无论运行到哪里,我都要他暂停”这样的能力。
我的问题是什么一个问题呢:有一个循环需要处理一些任务,但是这个任务必须要能够限制一轮的执行时间在比如50ms内完成,如果不能够完成也必须让位给后面的工作了。
一开始我是打算用Thread.Join(timeout) + Thread.Abort() 的方式来进行的,但是考虑到这样需要不停的产生线程和销毁(甚至终止)线程,开销有点大。此外Abort除了引发Exception占用更多的开销之外,还可能引发不可控制的后果,比如某个资源正在初始化到一半的时候就终止了。因此最终的修改方案是通过AutoResetEvent.WaitOne(timeout) * 2 + Thread.Suspend() + Thread.Resume来完成的。大致的代码如下:
AutoResetEvent evMain = new ...(false);
AutoResetEvent evLoop = new ...(false);
Thread loopThread = new ...(new ThreadStart(Loop));
// 该函数会被外部的一个大循环不断的调用
void MainLoop()
{
if (loopThread.ThreadState == ThreadState.Unstarted)
{
loopThread.Start(); // 开始循环线程
}
else
{
loopThread.Resume(); // 唤醒上一次被挂起的线程
evLoop.Set(); // 允许进行下一轮的处理(无论上一次是否因为超时被提前暂停)
}
evMain.WaitOne(timeout); // 等待处理,直到完成该轮循环或者超时
loopThread.Suspend(); // 挂起循环线程,无论他是否已经完成当前的处理了。
}
// 需要限制时间的任务
void Loop()
{
for (i = 0; i < c; i++)
{
call_the_process[i](); // 外部的、可能是其他人写的代码。
}
evMain.Set(); // 当前循环已经完成,允许主线程继续下面的代码。
evLoop.WaitOne(); // 等待下一次循环的机会
}
对于这样的一个情况,有没有可能不用suspend呢?需要指出的是,我没有办法控制任何一个call_the_process[i]所可能花费的时间,完全有可能某一个调用需要花费1000ms,因此不太可能在每一次循环的时候检查状态。另外,对于这样的线程间同步的问题(实际上应该说是限制某个循环任务的执行时间的问题),是否有一个比较好的Pattern呢?上面这个是我凭空想出来的,目前工作还算良好。不过到了whidbey下面有warning实在是太难看了,能够有更好的方法解决自然最好,否则怎么说也得要禁止这个warning的显示才行。
诸位有什么好建议呢?
打印 | 张贴于 2004-06-25 16:58:00 | Tag:.NET 技术内幕 游戏

留言反馈
You can update the screen every 10th of second. Thread scheduling should magically take care of your scheduling problem.
Could you write an english version of your problem, and send it to me via Contact in my blog? I can ask in our internal discussion.
Thanks,
Junfeng