.NET Thread.再次中止

发布于 2024-08-18 09:09:29 字数 760 浏览 3 评论 0原文

我想再次谈谈 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

后来的我们 2024-08-25 09:09:29

通过人为的测试,您可以证明任何事情。

您所证明的只是,使用您为测试编写的代码,Thread.Abort 似乎工作正常。

然而问题是,一旦你开始使用需要处理的东西,所有的希望都消失了。

例如,尝试以下代码:

using (Stream stream = new FileStream(@"C:\Test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{
    Thread.Sleep( Random.Next( 45, 55 ) );
}

现在,运行一段时间并告诉我它是否仍然有效。

当代码离开您的 sleep 调用,并且位于 using 块的隐式 finally 块内,并且即将关闭您的流,然后您中止它时,就会出现问题。

Thread.Abort 的问题是它可能发生在任何地方,甚至在不应该抛出异常的代码中也是如此。

例如,您是否真的希望以下代码在计算 if 表达式之后、但在 Dispose 调用消失之前崩溃?通过?

if (_ObjectToDispose != null)
{
    _ObjectToDispose.Dispose();
    _ObjectToDispose = null;
}

如果它发生在调用 .Dispose 之后怎么办?该字段仍将具有非空值,这可能会在其他地方导致微妙的问题。

如果您这样做会怎样:

IDisposable objectToDispose = Interlocked.Exchange(ref _ObjectToDispose, null);
if (objectToDispose != null)
    objectToDispose.Dispose();

使用此代码,您获取该值,将其替换为 null,然后在您开始调用 Dispose 之前,会发生 ThreadAbortException ,这只会留下该对象。

让我简单地阐述一下这一点:

绝对不应该使用 Thread.Abort,除非您需要终止程序(或拆除其中运行线程的自定义 AppDomain)。您不应该永远调用Thread.Abort,然后继续运行。

除非您需要将错误计划到未来的计划中。在这种情况下,请继续使用 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:

using (Stream stream = new FileStream(@"C:\Test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{
    Thread.Sleep( Random.Next( 45, 55 ) );
}

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?

if (_ObjectToDispose != null)
{
    _ObjectToDispose.Dispose();
    _ObjectToDispose = null;
}

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:

IDisposable objectToDispose = Interlocked.Exchange(ref _ObjectToDispose, null);
if (objectToDispose != null)
    objectToDispose.Dispose();

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:

Thread.Abort should never be used, except in scenarios where you need to terminate the program (or tear down a custom AppDomain with threads running in it). You should never call Thread.Abort and then continue running.

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.

放低过去 2024-08-25 09:09:29

使用线程中止是足够安全的。然而,正如其他人提到的,线程中止可能不会立即中止。调用线程中止将在线程中引发 ThreadAbortException。要清理资源,您可以捕获此异常并进行必要的清理。

static void Run()
{
  try 
  {
    while(someCondition)
    {
       ....
       ....
       ....
       if (someOtherCondition)
          throw new ThreadAbortException("Thread aborted");
    }
  }
  catch(ThreadAbortException e)
  {
    ...
    ... //clean up resources here.
    ...
  }
  finally
  {
    ...
  }  
}

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.

static void Run()
{
  try 
  {
    while(someCondition)
    {
       ....
       ....
       ....
       if (someOtherCondition)
          throw new ThreadAbortException("Thread aborted");
    }
  }
  catch(ThreadAbortException e)
  {
    ...
    ... //clean up resources here.
    ...
  }
  finally
  {
    ...
  }  
}
极致的悲 2024-08-25 09:09:29

使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文