首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止多个线程写入同一个文件

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

Stack Overflow用户
提问于 2014-04-28 14:16:23
回答 4查看 3.6K关注 0票数 1

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

如果使用不当,可能会发生同一文件被多个线程下载和写入的情况,这将导致在写入磁盘时出现异常。

我希望避免在写入文件的部分周围使用lock() { ... },但显然我不想使用全局对象锁定,只是与特定文件相关的内容,这样在写入文件时并不会锁定所有线程。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-04-28 14:23:43

您可以考虑使用ReaderWriterLockSlim

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

代码语言:javascript
复制
private ReaderWriterLockSlim fileLock = new ReaderWriterLockSlim();


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

Stack Overflow用户

发布于 2014-04-28 15:04:54

因此,您想要做的是同步一组没有给定键的操作。在这种情况下,该键可以是一个绝对文件名。我们可以将其实现为将键映射到某些同步对象的字典。如果我们想要实现阻塞同步机制,这可以是一个要锁定的对象,或者如果我们希望在适当的时候表示运行代码的异步方法,则可以是一个Task;我还使用了一个ConcurrentDictionary来让它处理同步,而不是手动处理它,并使用Lazy来确保每个任务只创建一次:

代码语言:javascript
复制
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,如果您没有任何需要等待,那么您就不能。这还允许您通过等待任务异步完成处理。

票数 3
EN

Stack Overflow用户

发布于 2014-04-28 14:30:42

我也遇到过类似的情况,并通过对所讨论的lock()对象进行StreamWriter处理来解决这个问题:

代码语言:javascript
复制
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
    }

这是从内存中得到的,它可能不会编译。我读了安德鲁的解决方案(我会的),因为这可能是你所需要的.但这太简单了,如果你只是想要一个既快又脏的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23343490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档