具有超时的WriteAsync [英] WriteAsync with timeout
问题描述
我尝试编写一个具有超时的简单异步写入,如下所示,并且在缓冲区很大且等待时间很小的情况下,我希望该函数抛出TaskCanceledException。但是,这不会发生。 WriteAsync将阻塞许多秒钟,直到写入完成。我想念什么?
I try to code a simple async write with timeout as below and expect the function to throw a TaskCanceledException given a very large buffer and small waitTime. However, this does not happen. WriteAsync will block for many seconds until the write completes. What am I missing?
public async void WriteWithTimeout(Stream os, byte[] buf, int waitMs)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(waitMs); // cancel after waitMs milliseconds.
await os.WriteAsync(buf, 0, buf.Length, tokenSource.Token);
return;
}
从GUI线程调用:
try
{
WriteWithTimeout(response.OutputStream, buf100M, w1ms);
}
catch(OperationCanceledException e)
{
ConsoleWriteLine("Failed with exception: {0}", e.Message);
}
推荐答案
异步无效。它必须返回一个任务,您必须等待它。
You can't catch a async void. It must return a task and you have to await it.
public async Task WriteWithTimeout(Stream os, byte[] buf, int waitMs)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(waitMs); // cancel after waitMs milliseconds.
await os.WriteAsync(buf, 0, buf.Length, tokenSource.Token);
return;
}
gui代码
try
{
await WriteWithTimeout(response.OutputStream, buf100M, w1ms);
}
catch(OperationCanceledException e)
{
ConsoleWriteLine("Failed with exception: {0}", e.Message);
}
取消仍会发生,但您只是看不到它们。
The cancellations still happen but you just don't observe them.
更新:
os.WriteAsync(
只是一个同步完成,由 Task.Run(
在幕后 1 支持。取消令牌不会取消已经运行的 Task.Run(
。在这种情况下,最好的方法是将取消内容包装在 Task.WhenAny(
令牌也通过无限长的 Task.Delay(
。
It is possible that os.WriteAsync(
is just a synchronous completion just backed by a Task.Run(
behind the scenes1. The cancellation token won't cancel a already running Task.Run(
. In that case the best way is to wrap the cancellation up in a Task.WhenAny(
and pass in the token to there too via a infinitely long Task.Delay(
.
public async Task WriteWithTimeout(Stream os, byte[] buf, int waitMs)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(waitMs); // cancel after waitMs milliseconds.
var task = os.WriteAsync(buf, 0, buf.Length, tokenSource.Token);
var waitedTask = await Task.WhenAny(task, Task.Delay(-1, token));
await waitedTask; //Wait on the returned task to observe any exceptions.
}
1。例如,如果不将 FileOptions.Asynchronous
传递给构造函数,则这是 FileStream
的默认行为
1. For example that is the default behavior of a FileStream
if you don't pass inFileOptions.Asynchronous
to the constructor
这篇关于具有超时的WriteAsync的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!