我想等待Task <T>完成一些特殊规则:如果在X毫秒后它还没有完成,我想向用户显示一条消息.如果它在Y毫秒后没有完成,我想自动请求取消.
我可以使用Task.ContinueWith异步等待任务完成(即安排在任务完成时执行的操作),但这不允许指定超时.我可以使用Task.Wait同步等待任务完成超时,但这会阻止我的线程.如何异步等待任务完成超时?
我们可以中止这样的线程:
Thread thread = new Thread(SomeMethod);
.
.
.
thread.Abort();
Run Code Online (Sandbox Code Playgroud)
但是我可以以相同的方式中止任务(在.Net 4.0中)而不是取消机制.我想立即杀死任务.
我有一个blackbox对象,它暴露了一个异步操作的方法,并在操作完成时触发一个事件.我已经将它包装到一个Task<OpResult> BlackBoxOperationAysnc()使用TaskCompletionSource 的方法中 - 效果很好.
但是,在那个异步包装器中,如果在给定的超时后没有收到事件,我想管理用超时错误完成异步调用.目前我使用计时器管理它:
public Task<OpResult> BlackBoxOperationAysnc() {
var tcs = new TaskCompletionSource<TestResult>();
const int timeoutMs = 20000;
Timer timer = new Timer(_ => tcs.TrySetResult(OpResult.Timeout),
null, timeoutMs, Timeout.Infinite);
EventHandler<EndOpEventArgs> eventHandler = (sender, args) => {
...
tcs.TrySetResult(OpResult.BlarBlar);
}
blackBox.EndAsyncOpEvent += eventHandler;
blackBox.StartAsyncOp();
return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
这是管理超时的唯一方法吗?有没有设置我自己的计时器 - 我在TaskCompletionSource中看不到任何超时?
我有几个异步网络操作返回可能永远不会完成的任务:
UdpClient.ReceiveAsync 不接受 CancellationTokenTcpClient.GetStream返回NetworkStream不尊重CancellationTokenon的Stream.ReadAsync(仅在操作开始时检查取消)两者都在等待可能永远不会发生的消息(例如因丢包或没有响应).这意味着我有永远不会完成的幻像任务,永远不会运行的延续和使用套接字.我知道我可以使用TimeoutAfter,但这只能解决延续问题.
那我该怎么办?
我的应用程序当前使用一些命令执行 Adobe Illustrator。当结果文件出现在某个确切的文件夹中(具有异步功能)时等待,并在文件准备好时对文件执行某些操作。
但问题是,有时 Adobe Illustrator 会失败并且应用程序一直等待。在这种情况下,我不知道如何应用超时机制来终止 Adobe Illustrator 并跳过当前进程。
这是代码:
...
await WhenFileCreated(result_file_name);
if (File.Exists(result_file_name))
{
...
public static Task WhenFileCreated(string path)
{
if (File.Exists(path))
return Task.FromResult(true);
var tcs = new TaskCompletionSource<bool>();
FileSystemWatcher watcher = new FileSystemWatcher(Path.GetDirectoryName(path));
FileSystemEventHandler createdHandler = null;
RenamedEventHandler renamedHandler = null;
createdHandler = (s, e) =>
{
if (e.Name == Path.GetFileName(path))
{
tcs.TrySetResult(true);
watcher.Created -= createdHandler;
watcher.Dispose();
}
};
renamedHandler = (s, e) =>
{
if (e.Name == Path.GetFileName(path))
{
tcs.TrySetResult(true);
watcher.Renamed -= renamedHandler;
watcher.Dispose(); …Run Code Online (Sandbox Code Playgroud) c# ×5
async-await ×2
timeout ×2
.net ×1
.net-4.0 ×1
asynchronous ×1
idisposable ×1
networking ×1
windows ×1