2010-05-11 35 views
8

我有一些代码启动一些线程让它们执行,然后使用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); 
+0

你不应该使用Thread.Abort,做一个谷歌的原因为什么。 – 2010-05-11 14:03:37

+2

10 * 1000不是一分钟:)(1000 * 60毫秒= 60秒= 1分钟) – Simon 2010-05-11 14:08:17

+0

是的,我知道:)我改变了这个测试的目的,但从未更新评论.... – BeckyLou 2010-05-11 14:14:55

回答

3

Thread.Abort的引发在调用它

你不应该让异常从你的线程永远逃脱线程一个ThreadAbortException - 你应该有线程对象中的异常处理。至少在线程对象的代码中应该有一个try \ catch块。

+0

谢谢,是的线程是循环并在循环中尝试/捕获。 ThreadAbortException结束该方法,并吞下或记录其他异常。 – BeckyLou 2010-05-11 14:14:04

5

所以,你真的不应该在线程上使用Sleep方法来实现同步。这是什么同步类,如ManualResetEvent,以及异步编程模型(IAsyncResult实现)。

这里的一个更好的方法是创建一个具有您想异步运行的方法的签名的委托。然后,将作为异步操作入口点的方法组分配给该委托的实例,并在委托实例上调用BeginInvoke。

从那里,你可以运行你的循环,希望你会叫的WaitOne过载上由调用的BeginInvoke对委托返回的IAsyncResult的执行AsyncWaitHandle属性返回的WaitHandle

这会减少对睡眠方法的依赖(这对一般同步不利)。

如果您可以选择使用.NET 4.0,那么您可能需要查看System.Threading.Tasks namespace中的Task class,因为它提供了一种更好的方式来处理异步处理,取消和等待超时。

+0

感谢你们,我以前使用过代表进行异步编程,但是我怎么能在两个代表之间的一段时间内强制停止处理呢? – BeckyLou 2010-05-11 14:22:50

+0

@BeckyLou:线程。中止绝对是错误的做法,因为它不是一个优雅的退出。像任何异步编程一样,您必须同步从等待线程和执行工作的线程访问标志。如果中止,则从等待线程写入,然后执行工作的线程会定期检查标志以确定是否应该停止工作。 .NET 4.0中的任务并行库(Task类)有很多内置的功能,所以我建议你在可能的情况下使用它。 – casperOne 2010-05-11 14:40:16

+0

谢谢,我会试试你的建议。 – BeckyLou 2010-05-11 14:45:01

相关问题