gpt4 book ai didi

c# - 这种方法是否比在 Task.Run 中触发 stream.Read() 更好?

转载 作者:太空狗 更新时间:2023-10-30 01:30:22 25 4
gpt4 key购买 nike

编辑:我并没有按照 discussion 最终采用这种方法与 Stephen Cleary .如果您对我的不同做法感兴趣,请查看我的 answer下面。

我正在寻找一种方法来异步读取带有超时的 NetworkStream。当然,问题在于无法取消 NetworkStream 上的 ReadAsync(),因为它会忽略 CancellationToken。我读到一个建议在 token 取消时关闭流的答案,但在我的情况下,这不是一个选项,因为 Tcp 连接必须保持打开状态。所以我想出了下面的代码,但我想知道这是否比做一个

Task.Run(() => stream.Read(buffer, offset, count)

只是阻塞了一个线程。

public static class TcpStreamExtension
{
public static async Task<int> ReadAsyncWithTimeout(this NetworkStream stream, byte[] buffer, int offset, int count)
{
CancellationTokenSource cts = new CancellationTokenSource();
bool keepTrying = true;
Timer timer = new Timer(stream.ReadTimeout);
timer.Elapsed += new ElapsedEventHandler((sender, args) => stopTrying(sender, args, cts, out keepTrying));
timer.Start();

try
{
if (stream.CanRead)
{
while (true)
{
if (stream.DataAvailable)
{
return await stream.ReadAsync(buffer, offset, count, cts.Token).ConfigureAwait(false);
}

if (keepTrying)
{
await Task.Delay(300, cts.Token).ConfigureAwait(false);
}
else
{
cts.Dispose();
timer.Dispose();
throw new IOException();
}
}
}
}
catch (TaskCanceledException tce)
{
// do nothing
}
finally
{
cts.Dispose();
timer.Dispose();
}
if (stream.DataAvailable)
{
return await stream.ReadAsync(buffer, offset, count).ConfigureAwait(false);
}

throw new IOException();
}

private static void stopTrying(object sender, ElapsedEventArgs args, CancellationTokenSource cts, out bool keepTrying)
{
keepTrying = false;
cts.Cancel();
}

}

该应用程序必须能够与数千个端点进行通信,我希望以一种不会阻塞一堆线程的方式创建它,因为它所做的大部分工作都是 IO。另外,超时的情况应该是

最佳答案

首先,您尝试做的事情存在根本性缺陷。您应该始终从一个开放的 TCP/IP 流中读取 - 一旦一次读取获得一些数据,就将其传递并开始下一次读取。

因此,我的第一个建议是首先需要可取消读取。相反,请始终阅读。同样,使用 DataAvailable 是一种代码味道。

更多解释...

对于不可取消的代码,没有一种“强制”取消的好方法。关闭 TCP/IP 套接字是最简单和最干净的方法。您现有的解决方案将不起作用,因为 ReadAsync 忽略了 CancellationToken。所以它并不比只使用没有计时器的 CancellationToken 好多少。如果 ReadAsync 忽略了 CancellationToken,您唯一真正的选择是关闭套接字。任何其他解决方案都可能导致“丢失数据”——从套接字读取但被丢弃的数据。

关于c# - 这种方法是否比在 Task.Run 中触发 stream.Read() 更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45464288/

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