中止线程时单独线程中任务的行为
Behaviour of tasks in separate thread on aborting the thread
我有一个特殊的线程设置和 Parallel.Foreach
:在一个单独的线程中执行一个 Parallel.Foreach
循环。调用函数 Abort()
可能会中止 Thread
。我的行为很奇怪:多次抛出 ThreadAbortException
。有人可以解释这里发生了什么,什么是好的解决方案?
系统:
- Visual Studio 2017
- C# 7.0
- .Net 4.6.1
下面的代码。
static void Main(string[] args)
{
//Start the new Thread
Thread workerThread = new Thread(Program.TestVoid);
workerThread.Name = "My WorkerThread";
workerThread.Start();
//wait
Thread.Sleep(1000);
//abort thread
workerThread.Abort();
}
public static void TestVoid()
{
bool[] liBools = new bool[10000];
Parallel.For(0, liBools.Length, idx =>
{
liBools[idx] = idx == 9998;
});
try
{
Parallel.ForEach(liBools, myBool =>
{
try
{
//do something
Thread.Sleep(1000);
}
catch (Exception ex) //Thread Abort Exception get caught
{
}
});
}
catch (OperationCanceledException ex)
{
}
catch (ThreadAbortException ex) //Thread Abort Exception get caught
{
} //here arises another ThreadAbortException
finally
{
source.Dispose();
}
string s = "ready";
}
如果您查看 documentation for Thread.Abort,您会发现它的功能是抛出一个 ThreadAbortException
。如果这不是您想要的,请不要使用 Thread.Abort
。通常,您应该通过 completing/returning 从整个调用堆栈中优雅地退出线程,而不是调用 Thread.Abort
。如果您必须调用 Thread.Abort
,您应该准备好处理随之而来的异常。
The i get a strange behaviour: multiple times the ThreadAbortException
is thrown.
这是该异常的正常行为:
When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Because the thread can do an unbounded computation in the finally blocks or call Thread.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread.Join method. Join is a blocking call that does not return until the thread actually stops executing. (Source)
what would be a good solution
此时您可以使用 Thread.ResetAbort()
取消流产,但不调用 Thread.Abort()
几乎总是更好。可取消 Task
s 和检查易失性 "please stop now" 布尔值是两种选择。其他可能适用于您的用例。 Thread.Abort()
应该只保留用于按下大红色警报按钮的场景,如果是的话。
我有一个特殊的线程设置和 Parallel.Foreach
:在一个单独的线程中执行一个 Parallel.Foreach
循环。调用函数 Abort()
可能会中止 Thread
。我的行为很奇怪:多次抛出 ThreadAbortException
。有人可以解释这里发生了什么,什么是好的解决方案?
系统:
- Visual Studio 2017
- C# 7.0
- .Net 4.6.1
下面的代码。
static void Main(string[] args)
{
//Start the new Thread
Thread workerThread = new Thread(Program.TestVoid);
workerThread.Name = "My WorkerThread";
workerThread.Start();
//wait
Thread.Sleep(1000);
//abort thread
workerThread.Abort();
}
public static void TestVoid()
{
bool[] liBools = new bool[10000];
Parallel.For(0, liBools.Length, idx =>
{
liBools[idx] = idx == 9998;
});
try
{
Parallel.ForEach(liBools, myBool =>
{
try
{
//do something
Thread.Sleep(1000);
}
catch (Exception ex) //Thread Abort Exception get caught
{
}
});
}
catch (OperationCanceledException ex)
{
}
catch (ThreadAbortException ex) //Thread Abort Exception get caught
{
} //here arises another ThreadAbortException
finally
{
source.Dispose();
}
string s = "ready";
}
如果您查看 documentation for Thread.Abort,您会发现它的功能是抛出一个 ThreadAbortException
。如果这不是您想要的,请不要使用 Thread.Abort
。通常,您应该通过 completing/returning 从整个调用堆栈中优雅地退出线程,而不是调用 Thread.Abort
。如果您必须调用 Thread.Abort
,您应该准备好处理随之而来的异常。
The i get a strange behaviour: multiple times the
ThreadAbortException
is thrown.
这是该异常的正常行为:
When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Because the thread can do an unbounded computation in the finally blocks or call Thread.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread.Join method. Join is a blocking call that does not return until the thread actually stops executing. (Source)
what would be a good solution
此时您可以使用 Thread.ResetAbort()
取消流产,但不调用 Thread.Abort()
几乎总是更好。可取消 Task
s 和检查易失性 "please stop now" 布尔值是两种选择。其他可能适用于您的用例。 Thread.Abort()
应该只保留用于按下大红色警报按钮的场景,如果是的话。