取消令牌的任务?

时间:2013-09-07 05:32:11

标签: c# .net multithreading task-parallel-library async-await

鉴于取消令牌,我想创建一个等待它的任务,这是永远不会完成但可以取消。我需要这样的模式,IMO应该很常见:

async Task DoStuff(Task t, CancellationToken ct)
{
   // t was made from TaskCompletionSource, 
   // both t and ct are beyond my control

   Task t2 = TaskFromCancellationToken(ct);
   await Task.WhenAny(t, t2);

   // do stuff
}

我到目前为止最好的想法是:

Task TaskFromCancelationToken(CancellationToken ct)
{
    return Task.Delay(Timeout.Infinite, ct);
}

有没有更好的方法来实现这种逻辑?

2 个答案:

答案 0 :(得分:18)

它不是非常常见,但它足以成为我的AsyncEx库的一部分。我使用something like这个:

public static Task AsTask(this CancellationToken cancellationToken)
{
    var tcs = new TaskCompletionSource<object>();
    cancellationToken.Register(() => tcs.TrySetCanceled(),
        useSynchronizationContext: false);
    return tcs.Task;
}

答案 1 :(得分:9)

Task.Delay(Timeout.Infinite, cancellationToken)

您在问题中建议的答案是我所知道的最佳解决方案。原因如下:

  • 很安全
  • 需要非常小的代码
  • 标准图书馆

根据我的知识,很多人都大量使用Task.Delay方法,并且在Microsoft博客上也推荐使用TaskCompletionSource方法。 MSDN Example

为什么要自己编写代码(包括测试)来利用function myLogger(logString) { alert("Inside mylogger"); window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) { alert("Inside Local File System"); var absPath = cordova.file.externalRootDirectory; var fileDir = cordova.file.externalDataDirectory.replace(cordova.file.externalRootDirectory, ''); var fileName = "logfile.txt"; var filePath = fileDir + fileName; alert(filePath); fs.root.getFile(filePath, {create: true, exclusive: false}, function (fileEntry) { alert("Inside getFile method"); fileEntry.createWriter(function (fileWriter) { alert("Inside createwriter method"); fileWriter.seek(fileWriter.length); // Start write position at EOF. var logStringWithTimeStamp = Date.parse(new Date()) + " : " + logString + "\n"; var blob = new Blob([logStringWithTimeStamp], {type: 'text/plain', endings: 'native'}); fileWriter.write(blob); }, function (err) { console.log("Err logString" + err); }); }, function (err) { console.log("Err" + err); }); }, function (err) { console.log("Err1" + err); }); } myLogger("Hello Logger"); 将取消令牌转换为任务?最好是利用标准库而不是重新发明轮子;它们比你的代码更容易出错。