为啥我的代码停止并且不返回异常?
Posted
技术标签:
【中文标题】为啥我的代码停止并且不返回异常?【英文标题】:Why is my code stopping and not returning an exception?为什么我的代码停止并且不返回异常? 【发布时间】:2011-02-18 04:08:14 【问题描述】:我有一些代码启动几个线程让它们执行,然后使用 while 循环检查当前时间是否超过了设定的超时期限,或者是否已处理正确数量的结果(通过检查类对象上的 int)(使用 Thread.Sleep()
在循环之间等待)
while 循环设置为退出后,它会在线程上调用Abort()
,并应将数据返回给调用该方法的函数。
在调试和单步执行代码时,我发现在单独线程上运行的代码中可能存在异常,在某些情况下我会适当地处理这些异常,而在其他时候我不想做任何具体的事情。
我所看到的是我的代码进入了 while 循环并且线程休眠了,然后我的函数没有返回任何数据,无论是数据还是异常。代码执行完全停止。
有什么想法会发生什么吗?
代码示例:
System.Threading.Thread sendThread =
new System.Threading.Thread(new System.Threading.ThreadStart(Send));
sendThread.Start();
System.Threading.Thread receiveThread =
new System.Threading.Thread(new System.Threading.ThreadStart(Receive));
receiveThread.Start();
// timeout
Int32 maxSecondsToProcess = this.searchTotalCount * timeout;
DateTime timeoutTime = DateTime.Now.AddSeconds(maxSecondsToProcess);
Log("Submit() Timeout time: " + timeoutTime.ToString("yyyyMMdd HHmmss"));
// while we're still waiting to receive results & haven't hit the timeout,
// keep the threads going
while (resultInfos.Count < this.searchTotalCount && DateTime.Now < timeoutTime)
Log("Submit() Waiting...");
System.Threading.Thread.Sleep(10 * 1000); // 1 minute
Log("Submit() Aborting threads"); // <== this log doesn't show up
sendThread.Abort();
receiveThread.Abort();
return new List<ResultInfo>(this.resultInfos.Values);
【问题讨论】:
你不应该使用 Thread.Abort,做一个 google 的原因。 10*1000 不是一分钟 :) (1000 * 60 ms = 60 s = 1 min) 是的,我知道 :) 我出于测试目的更改了此内容,但从未更新评论.... 【参考方案1】:所以,你真的不应该在线程上使用 Sleep 方法来进行同步。这就是 ManualResetEvent 等同步类以及异步编程模型(IAsyncResult 实现)的用途。
这里更好的方法是创建一个带有您要异步运行的方法签名的委托。然后,将作为异步操作入口点的方法组分配给该委托的一个实例,并在该委托实例上调用 BeginInvoke。
从那里,您将运行您的循环,期望您将调用 WaitHandle 上的 WaitOne 重载,该重载由调用委托上的 BeginInvoke 返回的 IAsyncResult 实现的 AsyncWaitHandle 属性返回。
这将减少对 Sleep 方法的依赖(这通常不利于同步)。
如果您可以选择使用 .NET 4.0,那么您可能需要查看 System.Threading.Tasks namespace 中的 Task class,因为它提供了一种更好的方法来处理异步处理、取消和等待超时。
【讨论】:
谢谢你,我以前使用过委托进行异步编程,但我怎么能在两个委托的设定时间段后强制超时停止处理? @BeckyLou:Thread.Abort 绝对是错误的方式,因为它不是一个优雅的退出。像任何异步编程一样,您必须同步从等待线程和执行工作的线程对标志的访问。如果中止,则从等待线程写入,然后执行工作的线程定期检查标志以查看它是否应该停止工作。 .NET 4.0 中的 Task Parallel 库(Task 类)为您内置了很多这样的功能,所以如果可能的话,我建议您看看。 谢谢,我会试试你的建议。【参考方案2】:Thread.Abort 在调用它的线程中引发 ThreadAbortException
你不应该让异常从你的线程中逃逸——你应该在你的线程对象中处理异常。至少应该在线程对象中的代码周围有一个 try\catch 块。
【讨论】:
谢谢,是的,线程是循环,并且在循环中有 try/catch。一个 ThreadAbortException 结束该方法,其他异常被吞下或记录。以上是关于为啥我的代码停止并且不返回异常?的主要内容,如果未能解决你的问题,请参考以下文章