有一项顶级任务可以启动另一项任务。
var token = _cancellationTokenSource.Token;
_task = new Task(() => WorkAction(this, token), token); //Top level task
内部任务实现是:
public string FindDevice(IProgressViewModel progressViewModel,
CancellationToken cancellationToken) {
for (int i = 0; i < orderedComPortsList.Count; i++) {
try {
cancellationToken.ThrowIfCancellationRequested();
} catch (OperationCanceledException) {
return null;
}
string curPort = orderedComPortsList[i];
if (InnerIsDeviceOnline(deviceModelId, curPort)) //The real long work
return curPort;
progressViewModel.CurrentValue = i;
}
return null;
}
通过此实现,仅当最后一个InnerIsDeviceOnline结束时才会取消。如何实现FindDevice使其立即取消?
更新1。
我们可以这样做:
bool? result = null;
Task<bool> parent = new Task<bool>(() => {
bool? res = result;
Task.Factory.StartNew(() => {
while (res==null) {
cancellationToken.ThrowIfCancellationRequested();
Thread.Sleep(50);
}
}, TaskCreationOptions.AttachedToParent);
result = InnerIsDeviceOnline(deviceModelId, comPort);
return result.Value;
}, cancellationToken);
return parent;
问题在于它永远不会完成(我不知道为什么)。但这会立即取消。
答案 0 :(得分:1)
为了优雅地取消长时间运行的操作,您的整个API需要以您需要的特定粒度支持取消。如果长时间运行的API不支持CancellationToken
,则您需要提供一个接口层来提供该支持。例如,异步WebRequest.BeginGetResponse
不支持CancellationToken
,但我能够通过此扩展方法支持它,该方法调用Abort()
以响应CancellationToken
被取消: