使集合可用于两个进程

时间:2011-12-13 12:43:18

标签: c# multithreading serialization dictionary io

大家好我有一个字典,必须在两个不同的exe文件之间共享。第一个应用程序创建一个密钥,然后将其存储在字典中,然后另一个应用程序创建一个密钥并将其存储在字典中。

目前我这样做:

private static void WriteToFile(Dictionary<string, byte[]> dictionary, string path)
    {
        Contract.Requires(dictionary != null);
        Contract.Requires(!string.IsNullOrEmpty(path));

        if (!(timestamp == File.GetLastWriteTime(DatabasePath)))
        {
            using (FileStream fs = File.OpenWrite(path))
            using (var writer = new BinaryWriter(fs))
            {
                // Put count.
                writer.Write(dictionary.Count);

                // Write pairs.
                foreach (var pair in dictionary)
                {
                    writer.Write(pair.Key);
                    writer.Write(pair.Value);
                }
                timestamp = DateTime.Now;
                File.SetLastWriteTime(DatabasePath, timestamp);

            }
        }
    }

    /// <summary>
    /// This is used to read a dictionary from a file
    /// http://www.dotnetperls.com/dictionary-binary
    /// </summary>
    /// <param name="path">The path to the file</param>
    /// <returns>The dictionary read from the file</returns>
    private static Dictionary<string, byte[]> ReadFromFile(string path)
    {
        Contract.Requires(!string.IsNullOrEmpty(path));
        var result = new Dictionary<string, byte[]>();
        using (FileStream fs = File.OpenRead(path))
        using (var reader = new BinaryReader(fs))
        {
            // Determine the amount of key value pairs to read.
            int count = reader.ReadInt32();

            // Read in all the pairs.
            for (int i = 0; i < count; i++)
            {
                string key = reader.ReadString();
                //// The byte value is hardcoded as the keysize is consistent
                byte[] value = reader.ReadBytes(513);
                result[key] = value;
            }
        }
        return result;
    }

然后,当我想存储一个密钥时,我称之为:

public static bool StoreKey(byte[] publicKey, string uniqueIdentifier)
    {
        Contract.Requires(ValidPublicKeyBlob(publicKey));
        Contract.Requires(publicKey != null);
        Contract.Requires(uniqueIdentifier != null);
        Contract.Requires(uniqueIdentifier != string.Empty);
        bool success = false;

        if (File.Exists(DatabasePath))
        {
            keyCollection = ReadFromFile(DatabasePath);
        }

        if (!keyCollection.ContainsKey(uniqueIdentifier))
        {
            if (!keyCollection.ContainsValue(publicKey))
            {
                keyCollection.Add(uniqueIdentifier, publicKey);
                success = true;

                WriteToFile(keyCollection, DatabasePath);
            }
        }
        return success;
    }

当程序生成密钥时,当我们尝试访问它们时,它只有1个密钥,我做错了什么?键和字符串存储得很完美,但我只是担心它们会覆盖文件或其他东西。

非常感谢您,非常感谢任何帮助

PS:databasePath是我想要保存文件的路径,创建为字段。

3 个答案:

答案 0 :(得分:3)

由于您未提供有关字典中有多少项目等的信息,因此很难说究竟发生了什么,但您似乎遇到了某种文件访问问题从多个进程访问同一文件。

您可以使用命名的Mutex作为跨进程同步对象,因此在访问文件之前,您必须确保释放Mutex句柄,以便您可以获取所有权,其他进程可以在访问之前等待文件。

// Create a mutex
Mutex mutex = new Mutex(false, "DictionaryAccessMutex");

// Acquire an ownership
mutex.WaitOne();

// Release
mutex.ReleaseMutex();

编辑:新发现

此外,您尝试在读取后立即写入,因此可能FileSystem操作尚未完成,因此写入失败,我不确定100%在这个可能的.NET托管类中,如File / StreamReader / etc已经处理过案件,但我认为值得仔细检查你的情况,因为不是100%清楚发生了什么。因此,请尝试在读取和写入操作之间添加一些超时,如Thread.Sleep(500)

编辑:您可以做的另一件事是下载Process Monitor SysInternals utility并查看在访问给定文件时哪些操作失败。所以只需添加一个新的过滤器Path=file name,您就可以看到低级别的内容。

答案 1 :(得分:2)

并行写入文件通常不是最好的主意。你有两个选择:

  1. 使用互斥锁进行跨进程同步以管理对文件的访问。
  2. 将所有写入请求转发给拥有该文件的独占所有权并进行实际写入的第三个进程。

答案 2 :(得分:0)

因此,Process 1加载字典,添加项目,调用write。 因此,Process 2加载字典,添加一个项目,调用write。

你得到的是第二个写的,你不知道它会是哪一个。

尝试使这项工作比它的价值更麻烦,它将作为充气飞镖的未来证明。

Mutex在推送或第三个进程中维护字典。