异步写入多个线程的文件c#

Jef*_*ron 37 c# io file-io multithreading asynchronous

这是我的情况.我想在我的应用程序中尽可能高效地写入文件系统.该应用程序是多线程的,每个线程都可以写入同一个文件.有没有一种方法可以从每个线程异步写入文件,而不会让不同线程中的写入结合在一起,可以这么说?

我正在使用C#和.NET 3.5,我也安装了Reactive Extensions.

µBi*_*Bio 14

看看异步I/O.这将释放cpu以继续执行其他任务.
ReaderWriterLock结合为@Jack B Nimble提到

If by

尽可能高效地写入文件系统

你的意思是尽可能快地制作实际的文件I/O,你将很难加快速度,磁盘只是速度慢.SSD也许?

  • 这似乎没有解决这个问题,即"砰然一起"的问题. (4认同)
  • 与处理多线程系统中的任何资源争用的方式相同.锁.ReadWriterLock(或ReaderWriterLockSlim with 4.0/Parallel Extensions + 3.5)允许多个读取同时发生,因此,如果这是您想要的,请使用它. (3认同)

Mat*_*ius 12

对于那些喜欢代码的人,我使用以下来从Web应用程序进行远程日志记录...

public static class LoggingExtensions
{
    static ReaderWriterLock locker = new ReaderWriterLock();
    public static void WriteDebug(this string text)
    {
        try
        {
            locker.AcquireWriterLock(int.MaxValue); //You might wanna change timeout value 
            System.IO.File.AppendAllLines(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", ""), "debug.txt"), new[] { text });
        }
        finally
        {
            locker.ReleaseWriterLock();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这能为您节省一些时间

  • 指定的问题*异步*。这都是同步的。 (2认同)
  • @Servy我在3个单独的线程中使用了它,所有文本都将它写入文件.同步与否这个解决方案对我有用而不会丢失数据.另外,请原谅我,如果我错了,但不仅仅是IO同步?异步的解决方案是在IO被锁定时收集字符串,并且一旦解锁就将收集写入文件,希望维持秩序. (2认同)
  • @Servy 我假设......但是大多数人不知道什么......当他们得到有效的解决方案时,他们通常会感激......在我的辩护中,我可以说是OP发起了它。 ..如果我给你的代码可以从多个线程异步写入文件,你会得到胡言乱语......你知道......所以关于答案正确性的整个论点有点毫无意义。是的,我对不正确的问题给出了错误的答案,为来这里的人解决了问题,每个人(除了你)都很高兴,哈哈......不要相信我发布正确答案,看看会发生什么...... (2认同)

Bob*_*yan 8

我要做的是有单独的工作线程专门用于编写文件的任务.当你的其他一个线程需要写出一些数据时,它应该调用一个函数来将数据添加到ArrayList(或其他一些容器/类).在这个函数中,顶部应该有一个lock语句,以防止同时执行多个线程.在添加对ArrayList的引用之后,它返回并继续其杂务.有几种方法可以处理写入线程.可能最简单的是简单地将它放入一个带有睡眠语句的无限循环中,这样它就不会咀嚼你的cpu.另一种方法是使用线程原语,并在没有更多数据要写出时进入等待状态.此方法意味着您必须使用类似ManualResetEvent.Set方法的方法激活线程.

有许多不同的方法可以在.NET中读入和写出文件.我写了一个基准程序并在我的博客中给出结果:

http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp

如果您需要性能,我建议使用Windows ReadFile和WriteFile方法.避免使用任何异步方法,因为我的基准测试结果表明使用同步I/O方法可以获得更好的性能.

Bob Bryan MCSD


Cam*_*ron 6

虽然基于线程的锁可以解决这个问题,但是有一种方法可以跨线程工作,但是当你有多个进程写入单个文件的末尾时,最好使用它.

要在进程(或线程)之间获得此行为,请指定在创建OS文件句柄时希望对操作系统进行原子追加写入.这是通过在Posix(Linux,Unix)下指定O_APPEND和在Windows下指定FILE_APPEND_DATA来完成的.

在C#中,您不直接调用操作系统'open'或'CreateFile'系统调用,但有多种方法可以获得此结果.

我问过一段时间以前在Windows下如何做到这一点,并在这里得到了两个好的答案:如何在C#中进行原子写/附加,或者如何使用FILE_APPEND_DATA标志打开文件?

基本上,您可以使用FileStream()或PInvoke,我建议使用PInvoke上的FileStream(),原因很明显.

您可以使用参数的构造函数对FILESTREAM()来指定我异步文件/除了FileSystemRights.AppendData标志,它应该给你两个异步I/O和原子追加写入文件O操作.

警告:某些操作系统对可以原子方式写入的最大字节数有限制,超过该阈值将删除操作系统的原子性承诺.

由于这个最后的问题,我建议在尝试在单个进程中解决您的问题时保持lock()样式争用管理.


Jac*_*ble 5

使用Reader / Writer锁来访问文件流。