具有超时的WriteAsync

Chu*_*Bun 1 c# outputstream async-await cancellationtokensource

我尝试使用如下所示的超时编写一个简单的异步写入,并期望该函数在给定非常大的缓冲区和小waitTime时抛出TaskCanceledException.但是,这不会发生.WriteAsync将阻塞很多秒,直到写入完成.我错过了什么?

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;
}
Run Code Online (Sandbox Code Playgroud)

从GUI线程调用:

try
{
    WriteWithTimeout(response.OutputStream, buf100M, w1ms);
}
catch(OperationCanceledException e)
{
    ConsoleWriteLine("Failed with exception: {0}", e.Message);
}        
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 10

你无法捕获异步空白.它必须返回一个任务,你必须等待它.

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;
}
Run Code Online (Sandbox Code Playgroud)

gui代码

try
{
    await WriteWithTimeout(response.OutputStream, buf100M, w1ms);
}
catch(OperationCanceledException e)
{
    ConsoleWriteLine("Failed with exception: {0}", e.Message);
}
Run Code Online (Sandbox Code Playgroud)

取消仍然发生,但你只是没有观察它们.

更新:

有可能os.WriteAsync(只是一个由Task.Run(幕后1支持的同步完成.取消令牌不会取消已经运行的Task.Run(.在这种情况下,最好的方法是将取消包装在a中,Task.WhenAny(并通过无限长的时间将令牌传递到那里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.
}
Run Code Online (Sandbox Code Playgroud)

1.例如,FileStream如果您没有传入FileOptions.Asynchronous构造函数,那么这是a的默认行为