.NET Thread.再次中止
我想再次谈谈 Thread.Abort 函数的安全性。我很感兴趣有某种方法来中止我无法真正控制并且实际上不想要的操作,但我希望尽快释放我的线程以防止线程渴求我的应用程序。
因此,我编写了一些测试代码,看看是否可以使用 Thread.Abort 并让中止线程正确清理资源。代码如下:
int threadRunCount = 0;
int threadAbortCount = 0;
int threadFinallyCount = 0;
int iterations = 0;
while( true )
{
Thread t = new Thread( () =>
{
threadRunCount++;
try
{
Thread.Sleep( Random.Next( 45, 55 ) );
}
catch( ThreadAbortException )
{
threadAbortCount++;
}
finally
{
threadFinallyCount++;
}
} );
t.Start();
Thread.Sleep( 45 );
t.Abort();
iterations++;
}
到目前为止,这段代码运行了大约 5 分钟,并且 threadRunCount
始终等于 threadFinally
,而 threadAbort
的数量要少一些,因为有些线程没有中止就完成了,或者可能最终中止了。
所以问题是,我错过了什么吗?
Again I want to talk about safety of the Thread.Abort
function. I was interested to have some way to abort operations which I can't control really and don't want actually, but I want to have my threads free as soon as possible to prevent thread thirsty of my application.
So I wrote some test code to see if it's possible to use Thread.Abort
and have the aborting thread clean up resources propertly. Here's code:
int threadRunCount = 0;
int threadAbortCount = 0;
int threadFinallyCount = 0;
int iterations = 0;
while( true )
{
Thread t = new Thread( () =>
{
threadRunCount++;
try
{
Thread.Sleep( Random.Next( 45, 55 ) );
}
catch( ThreadAbortException )
{
threadAbortCount++;
}
finally
{
threadFinallyCount++;
}
} );
t.Start();
Thread.Sleep( 45 );
t.Abort();
iterations++;
}
So, so far this code worked for about 5 mins, and threadRunCount
was always equal to threadFinally
and threadAbort
was somewhat lower in number, because some threads completed with no abort or probably got aborted in finally.
So the question is, do I miss something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
通过人为的测试,您可以证明任何事情。
您所证明的只是,使用您为测试编写的代码,
Thread.Abort
似乎工作正常。然而问题是,一旦你开始使用需要处理的东西,所有的希望都消失了。
例如,尝试以下代码:
现在,运行一段时间并告诉我它是否仍然有效。
当代码离开您的 sleep 调用,并且位于 using 块的隐式 finally 块内,并且即将关闭您的流,然后您中止它时,就会出现问题。
Thread.Abort
的问题是它可能发生在任何地方,甚至在不应该抛出异常的代码中也是如此。例如,您是否真的希望以下代码在计算 if 表达式之后、但在
Dispose
调用消失之前崩溃?通过?如果它发生在调用
.Dispose
之后怎么办?该字段仍将具有非空值,这可能会在其他地方导致微妙的问题。如果您这样做会怎样:
使用此代码,您获取该值,将其替换为 null,然后在您开始调用 Dispose 之前,会发生 ThreadAbortException ,这只会留下该对象。
让我简单地阐述一下这一点:
除非您需要将错误计划到未来的计划中。在这种情况下,请继续使用 Thread.Abort,因为我几乎可以保证您会遇到问题。
With a contrived test, you can prove anything.
All you have proved is that with the code you wrote for your test,
Thread.Abort
seems to work fine.The problem is, however, that as soon as you start using things that needs to be disposed of, all hope is lost.
For instance, try this code:
Now, run this for a while and tell me if that still works.
The problem appears when the code has left your sleep-call, and is inside the implicit finally-block for the using-block, and is just about to close your stream, and then you abort it.
The problem with
Thread.Abort
is that it can happen anywhere, even within code that isn't supposed to throw exceptions.For instance, do you really expect the following code to crash after the if-expression has been evaluated, but before the
Dispose
-call has gone through?What if it happens right after the call to
.Dispose
? The field will still have a non-null value, which could lead to subtle problems elsewhere.What if you do this:
With this code, you grab the value, replaces it with null, and then before you get around to calling Dispose, your
ThreadAbortException
happens, which will just leave the object.Let me just drive the point home:
Unless you need to plan bugs into your future schedule. In that case, go right ahead and use
Thread.Abort
, because I can almost guarantee you will have problems.使用线程中止是足够安全的。然而,正如其他人提到的,线程中止可能不会立即中止。调用线程中止将在线程中引发 ThreadAbortException。要清理资源,您可以捕获此异常并进行必要的清理。
Using thread abort is safe enough. However as mentioned by others that a thread abort may not get aborted immediately. Calling thread abort will raise a ThreadAbortException in the thread. To clean up resources you can catch this exception and do the necessary cleanups.
使用 Thread.Abort 就可以了。然而,它并不总是立即中止。如果线程正在执行非托管代码,则在返回托管代码之前它实际上不会中止。
Using Thread.Abort is fine. However, it does not always abort immediately. If a thread is doing unmanaged code, it won't actually abort until it returns to managed code.