如何中止/取消TPL任务?
在一个线程中,我创build了一些System.Threading.Task
并开始每个任务。
当我做.Abort()
来杀死线程时,任务不会中止。
如何将.Abort()
传输到我的任务?
你不能。 任务使用线程池中的后台线程。 不build议使用Abort方法取消线程。 您可以查看以下博客文章 ,其中解释了使用取消令牌取消任务的正确方法。 这是一个例子:
class Program { static void Main() { var ts = new CancellationTokenSource(); CancellationToken ct = ts.Token; Task.Factory.StartNew(() => { while (true) { // do some heavy work here Thread.Sleep(100); if (ct.IsCancellationRequested) { // another thread decided to cancel Console.WriteLine("task canceled"); break; } } }, ct); // Simulate waiting 3s for the task to complete Thread.Sleep(3000); // Can't wait anymore => cancel this task ts.Cancel(); Console.ReadLine(); } }
如果捕获正在运行任务的线程,则放弃任务很容易。下面是一个示例代码来演示此操作:
void Main() { Thread thread = null; Task t = Task.Run(() => { //Capture the thread thread = Thread.CurrentThread; //Simulate work (usually from 3rd party code) Thread.Sleep(1000); //If you comment out thread.Abort(), then this will be displayed Console.WriteLine("Task finished!"); }); //This is needed in the example to avoid thread being still NULL Thread.Sleep(10); //Cancel the task by aborting the thread thread.Abort(); }
我使用Task.Run()来显示最常见的用例 – 使用旧的单线程代码的舒适任务,它不使用CancellationTokenSource类来确定它是否应该被取消。
像这个post所build议的,这可以通过以下方式完成:
int Foo(CancellationToken token) { Thread t = Thread.CurrentThread; using (token.Register(t.Abort)) { // compute-bound work here } }
虽然有效,但不build议使用这种方法。 如果你能控制在任务中执行的代码,你最好去正确的处理取消。
这种事情是Abort
被弃用的后勤原因之一。 首先, 不要使用Thread.Abort()
来取消或停止一个线程,如果可能的话。 Abort()
只能用来强制杀死一个没有及时响应更多和平请求的线程。
这就是说,你需要提供一个共享的取消指标,一个线程设置并等待另一个线程定期检查并正常退出。 .NET 4包含专门为此devise的结构CancellationToken
。
你不应该直接尝试这样做。 devise你的任务来使用CancellationToken ,并以这种方式取消它们。
另外,我build议通过CancellationToken将主线程更改为函数。 调用Thread.Abort()
是一个坏主意 – 它可能导致各种难以诊断的问题。 相反,该线程可以使用与您的任务使用相同的“ CancellationTokenSource
并且可以使用相同的CancellationTokenSource
触发取消所有任务和主线程。
这将导致更简单,更安全的devise。
要回答Prerak K在不使用Task.Factory.StartNew()中的匿名方法时如何使用CancellationToken的问题,请将CancellationToken作为parameter passing给您以StartNew()开始的方法,如MSDN示例中所示这里 。
例如
var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; Task.Factory.StartNew( () => DoSomeWork(1, token), token); static void DoSomeWork(int taskNum, CancellationToken ct) { // Do work here, checking and acting on ct.IsCancellationRequested where applicable, }
您可以使用CancellationToken
来控制任务是否被取消。 你是说在开始之前放弃它(“我不知道,我已经做了这个”),还是实际上在中间打断它? 如果前者, CancellationToken
可以帮助; 如果是后者,则可能需要实现自己的“保释”机制,并在任务执行的适当位置检查是否应该快速失败(您仍然可以使用CancellationToken来帮助您,但手册更简单一些)。
MSDN有关于取消任务的文章: http : //msdn.microsoft.com/en-us/library/dd997396.aspx
我使用混合的方法取消任务。
- 首先,我试图取消它礼貌地使用取消 。
- 如果它仍然在运行(例如由于开发者的错误),那么使用老派的Abort方法会造成不正确的行为。
结帐一个例子如下:
private CancellationTokenSource taskToken; private AutoResetEvent awaitReplyOnRequestEvent = new AutoResetEvent(false); void Main() { // Start a task which is doing nothing but sleeps 1s LaunchTaskAsync(); Thread.Sleep(100); // Stop the task StopTask(); } /// <summary> /// Launch task in a new thread /// </summary> void LaunchTaskAsync() { taskToken = new CancellationTokenSource(); Task.Factory.StartNew(() => { try { //Capture the thread runningTaskThread = Thread.CurrentThread; // Run the task if (taskToken.IsCancellationRequested || !awaitReplyOnRequestEvent.WaitOne(10000)) return; Console.WriteLine("Task finished!"); } catch (Exception exc) { // Handle exception } }, taskToken.Token); } /// <summary> /// Stop running task /// </summary> void StopTask() { // Attempt to cancel the task politely if (taskToken != null) { if (taskToken.IsCancellationRequested) return; else taskToken.Cancel(); } // Notify a waiting thread that an event has occurred if (awaitReplyOnRequestEvent != null) awaitReplyOnRequestEvent.Set(); // If 1 sec later the task is still running, kill it cruelly if (runningTaskThread != null) { try { runningTaskThread.Join(TimeSpan.FromSeconds(1)); } catch (Exception ex) { runningTaskThread.Abort(); } } }
任务通过取消令牌获得一级支持取消 。 使用取消令牌创build您的任务,并明确地通过这些取消任务。
任务正在ThreadPool上执行(至less,如果你使用的是默认工厂),所以中止线程不会影响任务。 有关中止任务,请参阅msdn上的任务取消 。
- parsing器错误消息:无法加载types'TestMvcApplication.MvcApplication'
- Windows.Forms.Timer或System.Threading.Timer
- 在.Net中调用Web服务时,绕过无效的SSL证书错误
- 如何等待BackgroundWorker取消?
- 在C#中转换为“int”时,“const float”值与“float”不同
- 尝试方法'System.Web.Helpers.Json..cctor()'来访问方法'System.Web.Helpers.Json.CreateSerializer()'失败
- 检查一个对象是否是C#中的一个数字
- 有没有一个asp.net小提琴?
- VBCSCompiler.exe的许多实例