Mat*_*mas 5 c# cancellation async-await c#-4.0
如果您不输入任何输入,为什么下面的代码永远不会完成,为什么即使在取消标记被取消后它仍然响应按下的键?
// Set up a cancellation token
var cancellationSource = new CancellationTokenSource();
// Cancel the cancellation token after a little bit of time
Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(2));
cancellationSource.Cancel();
Console.WriteLine("Canceled the cancellation token");
});
// Wait for user input, or the cancellation token
Task.Run(async () =>
{
try
{
using (var input = Console.OpenStandardInput())
{
var buffer = new byte[1];
Console.WriteLine("Waiting for input");
await input.ReadAsync(buffer, 0, 1, cancellationSource.Token); // This is impossible to cancel???
Console.WriteLine("Done waiting for input"); // This never happens until you press a key, regardless of the cancellation token
}
}
catch (Exception e)
{
Console.WriteLine(e.Message); // No errors
}
})
.Wait(); // Block until complete
Run Code Online (Sandbox Code Playgroud)
如果操作在完成之前被取消,则返回的任务将包含 Status 属性的 Canceled 值。
这意味着取消取消令牌将取消操作,对吗?然而由于某种原因,如果没有事先取消,Stream.ReadAsync 的源代码不会对取消令牌做任何事情:
public virtual Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
// If cancellation was requested, bail early with an already completed task.
// Otherwise, return a task that represents the Begin/End methods.
return cancellationToken.IsCancellationRequested
? Task.FromCancellation<int>(cancellationToken)
: BeginEndReadAsync(buffer, offset, count);
}
Run Code Online (Sandbox Code Playgroud)
因此取消令牌参数毫无意义——我如何取消异步读取?
在控制台输入的特定情况下,除了轮询 Console.KeyAvailable 属性之外似乎没有其他方法:
var buffer = new byte[1];
Console.WriteLine("Waiting for input");
while (!Console.KeyAvailable && !cancellationSource.Token.IsCancellationRequested)
await Task.Delay(10); // You can add the cancellation token as a second parameter here, but then canceling it will cause .Delay to throw an exception
if (cancellationSource.Token.IsCancellationRequested)
{
Console.WriteLine("Canceled; no longer waiting for input");
}
else
{
await input.ReadAsync(buffer, 0, 1);
Console.WriteLine("Got user input");
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这表明您无法Stream.ReadAsync以通用方式可靠地使用,因为您必须根据您正在处理的 Stream 实现来执行不同的操作。
编辑:
再仔细考虑一下,您不能取消取消是有道理的ReadAsync,因为Stream抽象类没有任何处理异步操作的抽象方法;要实现 a ,您所要做的Stream就是实现一些 getter 和一些阻塞方法,这就是 Microsoft 对该__ConsoleStream类所做的全部工作。
由于唯一可以保证存在于 Stream 上的方法是阻塞方法,并且由于不可能取消阻塞调用(您甚至无法在另一个线程上执行阻塞 IO 操作、取消线程并让操作停止) ),不可能有可取消的异步操作。
因此,微软要么应该删除取消标记参数,要么应该将抽象的异步可取消方法放入类中,Stream以便制作者__ConsoleStream被迫实现它们。
| 归档时间: |
|
| 查看次数: |
3456 次 |
| 最近记录: |