C# 文件流的同步要求。(开始/结束)(读/写)

C# 文件流的同步要求。(开始/结束)(读/写),c#,.net,multithreading,file-io,filestream,C#,.net,Multithreading,File Io,Filestream,Net是否可以接受以下多线程调用模式 几个线程调用如下方法: 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.

Net是否可以接受以下多线程调用模式

几个线程调用如下方法:

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?
}
其中,
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
    }
}
我很困惑,因为文件对我来说似乎不清楚。例如,FileStream类表示:

此类型的任何公共静态成员都是线程安全的。任何实例成员都不能保证线程安全

但是BeginRead的文档似乎考虑了在飞行中有多个读取请求:

多个同步异步请求使得请求完成顺序不确定

是否允许在飞行中进行多次读取?写?这是确保流的
位置
在Seek调用和
BeginRead调用之间的位置的适当方法吗?或者该锁是否需要一直保持到
EndRead
,因此一次只能执行一次读写操作

我知道回调将发生在不同的线程上,我对
状态
缓冲区
的处理方式将允许多个正在进行的读取

此外,是否有人知道在文档中的何处可以找到这些问题的答案?或者是一篇知情人士写的文章?我一直在找,什么也找不到

相关文档:





编辑一些新信息


使用Reflector快速检查表明BeginRead确实将流位置捕获到每个调用状态(NativeOverlapped结构的某些字段)。EndRead似乎没有参考流位置,至少没有以任何明显的方式。显然,这不是结论性的,因为它可能是以不明显的方式出现的,或者它可能不受底层本机API的支持。

是的,文档很粗略。不幸的是,没有更好的医生的线索

编辑:实际上Joe Duffy的书《Windows上的并发编程》有第8章APM,其中解释了异步API、IAsyncResult等(好书和作者)。这里的基本问题仍然是MSDN说实例变量不是线程安全的,因此需要进行适当的同步


所以您有多个线程在同一个文件实例上启动BeginRead?但是,BeginRead页面确实提到了这一点:“每次调用BeginRead都必须准确调用EndRead一次。如果在开始另一次读取之前未能结束读取进程,则可能会导致死锁等不良行为。”另外,您正在调用文件对象上的查找,而其他线程可能在执行它们的开始读取回调的中间。一点也不安全。

如果一个线程正在查找,而另一个线程正在执行回调,那么这又有什么关系呢?可能回调意味着请求的读取已完成,对吗?我更关心的是在起始和匹配回调之间调用Seek。除非我遗漏了什么,否则上面的代码对BeginRead的每次调用只调用一次EndRead,对BeginRead在返回的IAsyncResult同步完成时是否调用其回调进行模化。是的,每个BeginRead都有一个EndRead。但是,不能保证在另一个线程开始它的起始线程之前调用EndRead,锁在这种情况下不起保护作用“在Windows上,所有小于64 KB的I/O操作都将同步完成,以获得更好的性能。对于小于64 KB的缓冲区大小,异步I/O可能会影响性能。因此,您可以保证所有读取实际上都是由锁序列化的。但是,如果所有线程都是通过锁和同步读取进行序列化的,那么为什么还要麻烦使用异步API呢?很好,我忽略了关于缓冲区大小的部分。我的问题是,是否需要保护在另一个线程开始其初始线程之前不会调用EndRead的场景。文档向我建议没有,或者为什么他们会说“多个同步异步请求导致请求完成顺序不确定”,而不是“多个同步异步请求不受支持/导致未定义的行为/会让恶魔飞出你的鼻子”解读MSDN让恶魔从我鼻子里飞出来;-)这个特定的页面肯定自相矛盾(MSDN文档错误并不少见),尽管我假设死锁语句是正确的,并且多个同步异步请求出错,但这只是一个假设。