gpt4 book ai didi

c# - 使用 Stream.BeginRead 的顺序异步读取

转载 作者:行者123 更新时间:2023-11-30 18:29:32 24 4
gpt4 key购买 nike

我正在编写一个类,该类公开流的一部分以供阅读。由于可能同时从多个不同的子部分读取数据,因此在任何时候只能进行一个操作。

我想到了在每次操作之前锁定底层流。在 BeginRead 调用周围锁定流是否足以确保从底层流中不同位置的并发异步读取正确发生?

public sealed class SubStream : Stream
{
// ...

public override IAsyncResult BeginRead(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
lock (this.baseStream)
{
this.baseStream.Seek(this.offset + this.position, SeekOrigin.Begin);
return this.baseStream.BeginRead(buffer, offset, count,
callback, state);
}
}

public override int EndRead(IAsyncResult asyncResult)
{
int read;
lock (this.baseStream)
{
read = baseStream.EndRead(asyncResult);
this.position += read;
}
return read;
}

// Read() and ReadByte() also lock on this.baseStream (not shown).

// ...
}

例如,如果线程 A 调用 BeginRead,则会获取基本流上的锁。现在线程 B 调用 BeginRead 并且必须等待锁被释放。线程 A 设置基本流的位置并启动异步读取操作。然后释放锁。线程 B 然后获取锁并更改基本流的位置并启动另一个异步读取操作。然后,稍后,线程 A 的异步读取完成。我可以确定这是从基本流中的原始位置读取的吗?如果没有,我该如何解决?

最佳答案

在这里,您最终可能会遇到多个线程在同一个资源实例 (baseStream) 上调用 BeginRead。根据 MSDN,“EndRead 必须在每次调用 BeginRead 时恰好调用一次。在开始另一次读取之前未能结束读取过程可能会导致不良行为,例如死锁。”在您的情况下,我侦察如果 Thread BSeek(在 baseStream 上)而 Thread A 正在执行它们的 EndRead(回调) '.

由于需求的性质,您最好使用同步 I/O 包装多线程访问。这意味着,当前的实现可以用同步 I/O 而不是异步 I/O 来修改。此外,您可能需要考虑使用 Monitor.WaitOne (baseStream)Monitor.Pulse(baseStream)Monitor 通知排队线程有关前一个线程的完成。 PulseAll(baseStream)

或者,我想提出另一个想法 Memory-Mapped分段样式的文件。

关于c# - 使用 Stream.BeginRead 的顺序异步读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22779526/

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