C# CancellationTokenSource是否突然取消?
假设我有这样的东西:C# CancellationTokenSource是否突然取消?,c#,.net,multithreading,asynchronous,task-parallel-library,C#,.net,Multithreading,Asynchronous,Task Parallel Library,假设我有这样的东西: private CancellationTokenSource myToken; public void MyMyMethod() { myToken = new CancellationTokenSource(); var task = Task.Factory.StartNew(() => DoIt(myToken.Token), myToken.Token); Thread.Sleep(100); myToken.Cancel(); } p
private CancellationTokenSource myToken;
public void MyMyMethod()
{
myToken = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => DoIt(myToken.Token), myToken.Token);
Thread.Sleep(100);
myToken.Cancel();
}
public void MyOtherMethod()
{
myToken.Cancel();
}
private void DoIt(CancellationToken token)
{
token.ThrowIfCancellationRequested();
try
{
for (int i = 0; i < 1000000; i++)
{
Console.WriteLine(i);
}
}
catch (Exception ex)
{
string s = "";
}
}
private CancellationTokenSource myToken;
公共void mymethod()
{
myToken=新的CancellationTokenSource();
var task=task.Factory.StartNew(()=>DoIt(myToken.Token),myToken.Token);
睡眠(100);
myToken.Cancel();
}
公共空间MyOtherMethod()
{
myToken.Cancel();
}
私有void DoIt(取消令牌令牌)
{
token.ThrowIfCancellationRequested();
尝试
{
对于(int i=0;i<1000000;i++)
{
控制台写入线(i);
}
}
捕获(例外情况除外)
{
字符串s=“”;
}
}
如果我调用myToken.Cancel,它会突然停止DoIt方法中的任务吗?还是我必须将令牌传递给DoIt并调用myToken.ThrowIfCancellationRequested()
,以便在调用Cancel时抛出异常并突然停止
如果不将令牌传递给任务方法,我是否可以执行此操作
或者我必须在DoIt方法中监视token.IsCancellationRequested吗?从这里读取,似乎在任务“真正”启动之前,但在任务排队之后,该令牌用于取消任务
这更像是一种取消已计划发生但尚未启动的任务的方法。一旦任务正在运行,取消它的唯一方法就是通过您自己在方法中的检查进行合作。如果没有这一点,您必须始终启动任务,然后在内部检查它,这将增加许多额外的、不必要的开销
您甚至可以通过从此处读取来从中读取该标记。该标记似乎用于在任务“真正”启动之前取消任务,但在任务排队之后取消任务
这更像是一种取消已计划发生但尚未启动的任务的方法。一旦任务正在运行,取消它的唯一方法就是通过您自己在方法中的检查进行合作。如果没有这一点,您必须始终启动任务,然后在内部检查它,这将增加许多额外的、不必要的开销
你甚至可以从报纸上读到它
我必须将令牌传递给DoIt并调用myToken.ThrowIfCancellationRequested()吗
是的,你知道。TPL取消是协作的,这意味着您的线程函数必须定期检查是否已请求取消,如果已请求,则自行终止
另一种方法是调用Thread.Abort()
,这通常不是一个好主意
我必须将令牌传递给DoIt并调用myToken.ThrowIfCancellationRequested()吗
是的,你知道。TPL取消是协作的,这意味着您的线程函数必须定期检查是否已请求取消,如果已请求,则自行终止
另一种方法是调用
Thread.Abort()
,这通常不是一个好主意。正如我当时猜测的那样,您必须监视方法中的IsCancellationRequested属性。如果方法中有各种循环等,那么这可能非常棘手。我希望有办法中止这项任务。为什么会很棘手呢ThrowIfCancellationRequested
抛出OperationCanceledException
,这在停止所有循环方面做得相当好:)@Anton他的意思是,如果任务被取消,他必须每隔几行检查一次。。。他希望在任务中神奇地注入一个异常来停止线程。。。不知道这正是Thread.Abort
所做的,并且它是邪恶的:-)所以我需要在我的方法中添加检查,以返回是否已取消,但异常抛出在哪里?@Jon在这里阅读了名为异常的部分,该部分表示合作取消
,正如我当时猜测的那样,您必须监视方法中的IsCancellationRequested属性。如果方法中有各种循环等,那么这可能非常棘手。我希望有办法中止这项任务。为什么会很棘手呢ThrowIfCancellationRequested
抛出OperationCanceledException
,这在停止所有循环方面做得相当好:)@Anton他的意思是,如果任务被取消,他必须每隔几行检查一次。。。他希望在任务中神奇地注入一个异常来停止线程。。。不知道这正是Thread.Abort
所做的,它是邪恶的:-)所以我需要在我的方法中添加检查,以在取消时返回,但异常抛出在哪里?@Jon在这里阅读了名为异常的部分,它表示合作取消
,因此,例如,我将调用throwifcancellationrequest,我假设它只设置了一个内部属性。然后我很好地结束了我的任务。然后我在某个地方抛出了一个异常?ThrowIfCancellationRequested()
抛出一个将终止线程函数的异常。TPL识别出这一点,并将任务标记为已取消
。这可能是我测试的方式,但线程仍在向控制台写入。查看我的更新问题和添加的代码。您需要在循环中调用ThrowIfCancellationRequested()
。您还需要在catch
块中重新抛出operationCanceledException
。或者您可以从循环中的特定位置使用if stmt-“if(myToken.IsCancellationRequested)”,以更优雅的方式明确地退出流程,并可能完成或清理您正在做的事情。当然,这需要以合理的时间间隔返回到循环中的那个位置,例如,我将调用throwifcancellationrequest,我假设它只设置了一个内部属性。然后我很好地结束了我的任务。然后我在某个地方抛出了一个异常?ThrowIfCancellationRequested()
抛出一个将终止线程函数的异常。TPL识别出这一点,并将任务标记为已取消
。这可能是我测试的方式,但线程仍在向控制台写入。查看我的更新问题和添加的代码。您需要