防止多个线程写入同一文件

时间:2014-04-28 14:16:24

标签: c# .net multithreading file-io mutex

我正在设计和开发一个api,其中多个线程从网上下载文件,然后将其写入磁盘。

如果使用不正确,可能会发生同一个文件被多个线程下载和写入,这会在写入磁盘时导致异常。

我想在编写文件的部分周围lock() { ... }避免这个问题,但显然我不想用全局对象锁定,只是与该特定文件相关的东西,所以不是全部写入文件时会锁定线程。

我希望这个问题是可以理解的。

4 个答案:

答案 0 :(得分:2)

您可以考虑使用ReaderWriterLockSlim

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

private ReaderWriterLockSlim fileLock = new ReaderWriterLockSlim();


fileLock.EnterWriteLock();
try
{
   //write your file here
}
finally
{
    fileLock.ExitWriteLock();
}

答案 1 :(得分:2)

所以你想要做的就是根据一个给定的密钥同步一堆动作。在这种情况下,该密钥可以是绝对文件名。我们可以将其实现为将键映射到某个同步对象的字典。如果我们想要实现阻塞同步机制,这可以是要锁定的对象,如果我们想要在适当时表示运行代码的异步方法,则可以是Task;我和后来一起去了。我还使用ConcurrentDictionary来让它处理同步,而不是手动处理它,并使用Lazy来确保每个任务只创建一次:

public class KeyedSynchronizer<TKey>
{
    private ConcurrentDictionary<TKey, Lazy<Task>> dictionary;
    public KeyedSynchronizer(IEqualityComparer<TKey> comparer = null)
    {
        dictionary = new ConcurrentDictionary<TKey, Lazy<Task>>(
            comparer ?? EqualityComparer<TKey>.Default);
    }

    public Task ActOnKey(TKey key, Action action)
    {
        var dictionaryValue = dictionary.AddOrUpdate(key,
            new Lazy<Task>(() => Task.Run(action)),
                (_, task) => new Lazy<Task>(() =>
                    task.Value.ContinueWith(t => action())));
        return dictionaryValue.Value;
    }

    public static readonly KeyedSynchronizer<TKey> Default =
        new KeyedSynchronizer<TKey>();
}

您现在可以创建此同步器的实例,然后指定操作以及它们对应的键(文件)。您可以确信,在完成对该文件的任何先前操作之前,不会执行这些操作。如果您想等到该操作完成,那么您可以Wait执行任务,如果您没有任何需要等待,那么您可以不这样做。这也允许您通过等待任务异步进行处理。

答案 2 :(得分:0)

我遇到了类似情况,并通过lock()StreamWriter对象解决了问题:

private Dictionary<string, StreamWriter>  _writers;  // Consider using a thread-safe dictionary

void  WriteContent(string file, string content)
    {
    StreamWriter  writer;
    if (_writers.TryGetValue(file, out writer))
        lock (writer)
            writer.Write(content);
    // Else handle missing writer
    }

那是内存,它可能无法编译。我会读到安德鲁的解决方案(我将会),因为它可能更准确地说你需要...但如果你只是想要一个快速而肮脏的话,这非常简单。

答案 3 :(得分:0)

我会用一些解释作出答案。

Windows已经有了某种你想要的东西,背后的想法很简单:允许多个进程访问同一个文件并进行所有的写/读操作,这样:1)所有进程都在运行该文件的最新数据2)多次写入或读取而不等待(如果可能)。

它被称为Memory-Mapped Files。我主要是将它用于IPC(没有文件),所以无法提供示例,但应该有some

您可以通过在其上使用一些缓冲区和排序层来模仿MMF行为,这会将所有读/写操作重定向到该缓冲区并定期将更新的内容刷新到物理文件中。

P.S:尝试查看文件共享(用于共享读/写的打开文件)。