C# 对任务使用CancellationToken。运行
我有一些使用C# 对任务使用CancellationToken。运行,c#,task,cancellationtokensource,C#,Task,Cancellationtokensource,我有一些使用任务的代码。使用取消令牌运行 这是我的密码: public class TaskObject { CancellationTokenSource _source = new CancellationTokenSource(); public async Task TaskAction() { var task = Task.Run(async delegate { await TaskRun();
任务的代码。使用取消令牌运行
这是我的密码:
public class TaskObject
{
CancellationTokenSource _source = new CancellationTokenSource();
public async Task TaskAction()
{
var task = Task.Run(async delegate
{
await TaskRun();
}, _source.Token);
//TaskCancel();
try
{
task.Wait();
}
catch (Exception ex)
{
}
}
public async Task TaskRun()
{
if (_source.IsCancellationRequested)
{
_source.Token.ThrowIfCancellationRequested();
}
SpeechSynthesizer _speechSynthesizer = new SpeechSynthesizer();
_speechSynthesizer.SpeakAsync("This is a test prompt");
}
public void TaskCancel()
{
_source.Cancel();
}
}
如果调用TaskAction()
中的taskanccel()
,将捕获任务取消异常
如果从对象外部调用TaskCancel()
,则不会捕获已取消的异常
以下是一些代码,用于演示未捕获已取消异常的位置:
taskObject = new TaskObject();
await taskObject.TaskAction();
taskObject.TaskCancel();
如何从对象外部调用TaskCancel()
,以便捕获已取消的异常?取消需要合作Task.Run
不知道计划的委托可能有什么副作用,因此,Task.Run
可以检查CancellationToken
并抛出OCE(而不会使应用程序处于潜在不一致的状态)的唯一逻辑安全点在异步操作开始之前-在该点之后,由用户代码检查令牌
问题是,您的用户代码大部分时间都在等待SpeechSynthesizer.SpeakAsync
,它没有接受取消令牌的重载
SpeechSynthesizer
有一个SpeakAsyncCancelAll
方法,您可以像这样插入它:
public async Task TaskRun(CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
SpeechSynthesizer _speechSynthesizer = new SpeechSynthesizer();
using (ct.Register(() => _speechSynthesizer.SpeakAsyncCancelAll())) {
await _speechSynthesizer.SpeakAsync("This is a test prompt");
}
}
我无法告诉您这是否会产生异常,表明操作已取消-您需要亲自尝试查看。取消需要合作Task.Run
不知道计划的委托可能有什么副作用,因此,Task.Run
可以检查CancellationToken
并抛出OCE(而不会使应用程序处于潜在不一致的状态)的唯一逻辑安全点在异步操作开始之前-在该点之后,由用户代码检查令牌
问题是,您的用户代码大部分时间都在等待SpeechSynthesizer.SpeakAsync
,它没有接受取消令牌的重载
SpeechSynthesizer
有一个SpeakAsyncCancelAll
方法,您可以像这样插入它:
public async Task TaskRun(CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
SpeechSynthesizer _speechSynthesizer = new SpeechSynthesizer();
using (ct.Register(() => _speechSynthesizer.SpeakAsyncCancelAll())) {
await _speechSynthesizer.SpeakAsync("This is a test prompt");
}
}
我无法告诉您这是否会产生一个异常,表明该操作已被取消-您需要亲自尝试查看。忽略SpeechSynthesizer,我说的对吗?启动Task.Run时,除非在函数开始时,否则无法检测取消请求?@user3736648,你似乎有正确的想法,但措辞需要润色(见第一段)。简单地说,Task.Run
在线程池上执行委托之前,一开始就检查一次CancellationToken
。一旦委托调用进行,就没有任何任务。运行可以完成。谢谢。除了Task.Run之外,是否有一种正确的方法来创建可以随时取消的线程?@user3736648,这在技术上是不可能的(因为这将使我们很难推断支持取消的系统的状态)。您需要的是协同取消(即支持本机取消的API,如我前面提到的speakasyncancelall
调用)。MSDN:当然,您可以放弃异步操作(在本例中为语音播放),但这正是它听起来的样子:即使取消了任务
,合成器仍将继续播放:忽略SpeechSynthesis,我所说的当启动Task.Run时,除非在函数开始时?@user3736648,您似乎有正确的想法,但措辞需要一些修饰(见第一段),否则无法检测取消请求。简单地说,Task.Run
在线程池上执行委托之前,一开始就检查一次CancellationToken
。一旦委托调用进行,就没有任何任务。运行可以完成。谢谢。除了Task.Run之外,是否有一种正确的方法来创建可以随时取消的线程?@user3736648,这在技术上是不可能的(因为这将使我们很难推断支持取消的系统的状态)。您需要的是协同取消(即支持本机取消的API,如我前面提到的speakasyncancelall
调用)。MSDN:当然,您可以放弃异步操作(在本例中为语音播放),但这正是它听起来的样子:合成器将继续播放,即使任务被取消: