gpt4 book ai didi

c# - 如何取消 Stream.ReadAsync?

转载 作者:行者123 更新时间:2023-12-03 17:05:30 36 4
gpt4 key购买 nike

如果您不输入任何输入,为什么下面的代码永远不会完成,为什么即使在取消标记被取消后它仍然响应按下的键?

// 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

The documentation for Stream.ReadAsync says :

If the operation is canceled before it completes, the returned task contains the Canceled value for the Status property.



这意味着取消取消 token 将取消操作,对吗?然而出于某种原因 the source code for Stream.ReadAsync如果未事先取消,则不会对取消 token 执行任何操作:
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);
}

因此取消 token 参数毫无意义——我如何取消异步读取?

最佳答案

在控制台输入的特殊情况下,除了轮询 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");
}

对我来说,这表明您不能可靠地使用 Stream.ReadAsync一般而言,因为您必须根据您正在处理的 Stream 实现来做不同的事情。

编辑:

再想一想,不能取消就说得通了 ReadAsync ,因为 Stream抽象类没有任何处理异步操作的抽象方法;实现 Stream 所必须做的一切实现了一些 getter 和一些阻塞方法,这就是微软对 __ConsoleStream 所做的一切。类(class)。

由于唯一可以保证存在于 Stream 上的方法是阻塞方法,并且由于无法取消阻塞调用(您甚至无法在另一个线程上执行阻塞 IO 操作,取消该线程并让操作停止),不可能有可取消的异步操作。

因此微软要么应该删除取消 token 参数,要么应该将抽象的异步可取消方法放入 Stream类(class)让制作的乡亲们 __ConsoleStream将被迫实现它们。

关于c# - 如何取消 Stream.ReadAsync?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42305825/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com