Dou*_*ean 9 .net c# file-io multithreading filestream
.Net FileStream是否可以接受以下多线程调用模式?
几个线程调用这样的方法:
ulong offset = whatever; // different for each thread
byte[] buffer = new byte[8192];
object state = someState; // unique for each call, hence also for each thread
lock(theFile)
{
theFile.Seek(whatever, SeekOrigin.Begin);
IAsyncResult result = theFile.BeginRead(buffer, 0, 8192, AcceptResults, state);
}
if(result.CompletedSynchronously)
{
// is it required for us to call AcceptResults ourselves in this case?
// or did BeginRead already call it for us, on this thread or another?
}
Run Code Online (Sandbox Code Playgroud)
在哪里AcceptResults:
void AcceptResults(IAsyncResult result)
{
lock(theFile)
{
int bytesRead = theFile.EndRead(result);
// if we guarantee that the offset of the original call was at least 8192 bytes from
// the end of the file, and thus all 8192 bytes exist, can the FileStream read still
// actually read fewer bytes than that?
// either:
if(bytesRead != 8192)
{
Panic("Page read borked");
}
// or:
// issue a new call to begin read, moving the offsets into the FileStream and
// the buffer, and decreasing the requested size of the read to whatever remains of the buffer
}
}
Run Code Online (Sandbox Code Playgroud)
我很困惑因为文档似乎对我不清楚.例如,FileStream类说:
此类型的任何公共静态成员都是线程安全的.任何实例成员都不保证是线程安全的.
但是BeginRead的文档似乎考虑在飞行中有多个读取请求:
多个同时发生的异步请求使请求完成顺序不确定.
允许多次读取是否在飞行中?写?这是在PositionSeek调用和调用之间保护流的位置的适当方法BeginRead吗?或者是否需要一直保持锁定EndRead,因此一次只能进行一次读写操作?
据我所知,回调将发生在不同的线程,和我的处理state,buffer处理在的方式,将允许多个飞行中读取.
此外,是否有人知道文档中的哪个位置可以找到这些问题的答案?或者有人知道的文章?我一直在寻找,找不到任何东西.
相关文件:
FileStream类
Seek方法
BeginRead方法
EndRead
IAsyncResult接口
使用一些新信息进行编辑
使用Reflector快速检查显示BeginRead确实将流位置捕获到每个调用状态(NativeOverlapped结构的某些字段).似乎EndRead不会查询流的位置,至少不是以任何明显的方式.显然,这不是决定性的,因为它可能是一种非显而易见的方式,或者它可能不受底层本机API的支持.
是的,文档很粗略。不幸的是,没有更好的文档的线索。
编辑:实际上 Joe Duffy 的书《Windows 上的并发编程》有第 8 章 APM,其中解释了异步 API、IAsyncResult 等(好书和作者)。这里的基本问题仍然是 MSDN 说实例变量不是线程安全的,因此需要适当的同步。
那么您有多个线程在 theFile 的同一个实例上启动 BeginRead 吗?不过,BeginRead 页面确实提到了这一点:“每次调用 BeginRead 时,必须调用一次 EndRead。如果在开始另一次读取之前未能结束读取过程,可能会导致死锁等不良行为。” 此外,您正在对 File 对象调用 Seek,而其他线程可能正在执行其 BeginRead 回调。一点也不安全。