多进程读取和写入一个文件

时间:2013-09-09 01:54:48

标签: c# multithreading

我有一个txt文件ABC.txt,它将由多个进程读取和写入。因此,当一个进程正在读取或写入文件ABC.txt时,必须锁定文件ABC.txt,以便任何其他进程无法读取或写入它。我知道枚举System.IO.FileShare可能是处理这个问题的正确方法。但我用另一种方式,我不确定它是否正确。以下是我的解决方案。

我在文件夹中添加了另一个文件Lock.txt。在我可以读取或写入文件ABC.txt之前,我必须能够从文件Lock.txt中读取。在我读取或写入文件ABC.txt后,我必须释放该功能。以下是代码。

        #region Enter the lock
        FileStream lockFileStream = null;
        bool lockEntered = false;
        while (lockEntered == false)
        {
            try
            {
                lockFileStream = File.Open("Lock.txt", FileMode.Open, FileAccess.Read, FileShare.None);
                lockEntered = true;
            }
            catch (Exception)
            {
                Thread.Sleep(500);
            }
        }
        #endregion

        #region Do the work
        // Read from or write to File ABC.txt
        // Read from or write to other files
        #endregion

        #region Release the lock
        try
        {
            if (lockFileStream != null)
            {
                lockFileStream.Dispose();
            }
        }
        catch
        {
        }
        #endregion

在我的电脑上,似乎此解决方案效果很好,但我仍然无法确定它是否合适。

编辑:多个进程,而不是同一进程中的多线程。

5 个答案:

答案 0 :(得分:41)

C#的名字EventWaitHandle是这里的方式。在每个想要使用该文件的进程中创建一个等待句柄实例,并为其指定一个由所有此类进程共享的名称。

EventWaitHandle waitHandle = new EventWaitHandle(true, EventResetMode.AutoReset, "SHARED_BY_ALL_PROCESSES");

然后在waitHandle上访问文件等待并完成处理文件后,设置它以便队列中的下一个进程可以访问它。

waitHandle.WaitOne();
/* process file*/
waitHandle.Set();

当您命名事件等待句柄时,该名称将在操作系统中的所有进程之间共享。因此,为了避免冲突的可能性,请使用guid作为名称(上面的“SHARED_BY_ALL_PROCESSES”)。

答案 1 :(得分:8)

C#中的互斥锁可以在多个进程之间共享。以下是写入单个文件的多个进程的示例:

using (var mutex = new Mutex(false, "Strand www.jakemdrew.com"))
{
    mutex.WaitOne();
    File.AppendAllText(outputFilePath,theFileText);
    mutex.ReleaseMutex();
}

您需要确保互斥锁具有唯一的名称,该名称将在整个系统中共享。

补充阅读:

http://www.albahari.com/threading/part2.aspx#_Mutex

答案 2 :(得分:3)

您的解决方案容易出错。您基本上实现了双重检查锁定(http://en.wikipedia.org/wiki/Double-checked_locking),这可能非常不安全。

更好的解决方案是引入线程隔离,从而只有一个线程访问该文件,并通过从其他线程放置读取或写入请求的队列读取(当然队列受到保护)通过线程的互斥访问)或线程通过同步设备(lock部分,mutices,等等)或通过使用一些其他文件访问逻辑(例如,System.IO.FileShare来自同步自己的位置)这里很少有人回应。)

答案 3 :(得分:0)

C#有一个内置的lock,您可以通过创建一个所有线程都可以访问的静态对象来使用它:

private static object lockObject {get;set;}

public static object LockObject {get{return lockObject ?? lockObject = new object();}}


void YourMethod()
{
   lock(LockObject)  // all other threads will wait for y
   {
      using(var lockFileStream = File.Open("Lock.txt", FileMode.Open, FileAccess.Read, FileShare.None))
      {
         //Do what you need with the file.  
      }

   }
}

这会为您的问题创建线程安全方法。

答案 4 :(得分:0)

如果是我,我会安装类似SQL Server Compact Edition的东西来读/写这些数据。

但是,如果您希望能够锁定对多个进程之间共享的资源的访问,则需要使用Mutex或Semaphore。

Mutex类是围绕OS级锁定机制的.Net包装器。

Overview of Synchronization Primitives