Pat*_*ier 144 .net c# multithreading task abort
在一个线程中,我创建一些System.Threading.Task并启动每个任务.
当我做一个.Abort()杀死线程时,任务不会中止.
我怎样才能传递.Abort()给我的任务?
Dar*_*rov 216
你不能.任务使用线程池中的后台线程.也不建议使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
Flo*_*ppl 30
如果捕获运行任务的线程,则可以轻松地中止任务.下面是一个示例代码来演示:
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();
}
Run Code Online (Sandbox Code Playgroud)
我使用Task.Run()来显示最常见的用例 - 使用旧的单线程代码使用Tasks,它不使用CancellationTokenSource类来确定是否应该取消它.
sta*_*ort 28
像这篇文章建议的那样,这可以通过以下方式完成:
int Foo(CancellationToken token)
{
Thread t = Thread.CurrentThread;
using (token.Register(t.Abort))
{
// compute-bound work here
}
}
Run Code Online (Sandbox Code Playgroud)
虽然它有效,但不建议使用这种方法.如果您可以控制在任务中执行的代码,则最好采用正确的取消处理方式.
Ada*_*son 17
这种事情是为什么Abort被弃用的后勤原因之一.首先,如果可能的话,不要使用Thread.Abort()取消或停止线程. Abort()应该只用于强制杀死一个没有及时响应更和平请求的线程.
话虽这么说,你需要提供一个共享取消指示器,一个线程设置并等待,而另一个线程定期检查并正常退出..NET 4包含专门为此目的而设计的结构CancellationToken.
你不应该试着直接这样做.设计您的任务以使用CancellationToken,并以这种方式取消它们.
另外,我建议你也可以通过CancellationToken更改你的主线程.呼叫Thread.Abort()是一个坏主意 - 它可能导致各种难以诊断的问题.相反,该线程可以使用您的任务使用的相同取消 - 并且可以使用相同的取消CancellationTokenSource来触发所有任务和主线程的取消.
这将导致更简单,更安全的设计.
要回答Prerak K关于如何在Task.Factory.StartNew()中不使用匿名方法时使用CancellationTokens的问题,请将CancellationToken作为参数传递给您从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,
}
Run Code Online (Sandbox Code Playgroud)
我使用混合方法取消任务.
查看以下示例:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
145897 次 |
| 最近记录: |