.Net 可以接受以下多线程调用模式吗文件流 http://msdn.microsoft.com/en-us/library/y0bs3w9t%28v=VS.90%29.aspx?
多个线程调用这样的方法:
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?
}
Where AcceptResults
is:
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
}
}
我很困惑,因为文档对我来说似乎不清楚。例如,FileStream 类表示:
此类型的任何公共静态成员都是线程安全的。不保证任何实例成员都是线程安全的。
但 BeginRead 的文档似乎考虑了多个读取请求:
多个同时异步请求导致请求完成顺序不确定。
飞行中是否允许多次读取?写?这是确保位置安全的适当方法吗?Position
调用 Seek 和调用之间的流BeginRead
?或者是否需要一直持有该锁EndRead
,因此一次只有一个在飞行中读取或写入?
我知道回调将发生在不同的线程上,并且我的处理state
, buffer
以允许多次飞行读取的方式处理该问题。
此外,有谁知道在文档中哪里可以找到这些问题的答案?或者有知情人士写的文章?我一直在寻找,但找不到任何东西。
相关文档:
文件流类 http://msdn.microsoft.com/en-us/library/y0bs3w9t%28v=VS.90%29.aspx
求方法 http://msdn.microsoft.com/en-us/library/883dhyx0.aspx
开始读取方法 http://msdn.microsoft.com/en-us/library/zxt5ahzw.aspx
EndRead http://msdn.microsoft.com/en-us/library/525xt96h.aspx
IAsyncResult 接口 http://msdn.microsoft.com/en-us/library/system.iasyncresult_members%28v=VS.90%29.aspx
编辑一些新信息
使用 Reflector 进行快速检查表明 BeginRead 确实将流位置捕获到每次调用状态(NativeOverlapped 结构的某些字段)。看起来 EndRead 不会查询流位置,至少不会以任何明显的方式。显然,这并不是决定性的,因为它可能是以一种不明显的方式,或者底层的本机 API 可能不支持。