【问题标题】:Changes to Buffer While BeginWrite is Called调用 BeginWrite 时对缓冲区的更改
【发布时间】:2014-10-01 22:00:41
【问题描述】:

我很好奇在 BeginWrite 实际完成写入之前对 byte[] 进行更改是否会影响 FileStream 最终写入的内容。

我在下面有这段代码,currentPage 是一个字节[],其中包含我要写入的数据。

try
{
FileStream.BeginWrite(currentPage, 0, currentPage.Length, new AsyncCallback(EndWriteCallback),new State(logFile.fs, currentPage, BUFFER_SIZE, manualEvent));
manualEvent.WaitOne();
}
catch (Exception e)
{
  //handle exception here
}

我在一个循环中有这个,它将替换 currentPage 中的数据。如果我对 currentPage 进行更改(例如分配一个全为 0 的新字节 [])会发生什么? FileStream 是否缓冲要写入某处的 byte[] 还是实际上只是引用了我在调用它时传入的 byte[]?

我尝试查看 MSDN 文章,但我只能找到

多个同时异步请求导致请求完成顺序不确定。

谁能给我解释一下?

【问题讨论】:

  • 对我来说,“不确定的完成顺序”意味着该函数不是线程安全的,这可能意味着对 byte[] 执行任何操作都可能导致意想不到的后果。
  • 是的,设备驱动程序直接从 currentPage 读取。 More here.

标签: c# asynchronous file-io


【解决方案1】:

此代码应该可以回答您的问题。首先,我创建一个长字节数组,其中每个单元格都等于 255。然后我启动 2 个线程。第一个负责将准备好的字节数组写入文件。同时,第二个线程修改了这个数组,从最后一个单元格开始,将每个单元格设置为 0。

执行此代码的确切结果将取决于机器、当前 CPU 使用率等。在我的计算机上,有一次我观察到大约 77% 的创建文件包含 255 秒,其余为 0 秒。下一次大约是70%。它确认输入数组没有被 BeginWrite 方法阻止写入。

为了观察这个效果,试着运行这个程序几次。可能还需要使用更长的数组。

var path = @"C:\Temp\temp.txt";

var list = new List<byte>();
for(var  i = 0; i < 1000000; ++i)
    list.Add(255);

var buffer = list.ToArray();

var t1 = Task.Factory.StartNew(() =>
{
    using (var fs = File.OpenWrite(path))
    {
        var res = fs.BeginWrite(buffer, 0, buffer.Length, null, null);
        res.AsyncWaitHandle.WaitOne();
    }
 });

var t2 = Task.Factory.StartNew(() =>
{
     for (var i = buffer.Length - 1; i > 0; --i)
         buffer[i] = 0;
});

Task.WaitAll(t1, t2);

【讨论】:

    猜你喜欢
    • 2012-01-31
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多