Словарь.NET: Потенциальные проблемы параллелизма?

Локальный путь к файлу не "file: //". Вы можете обычно читать файл, используя локальный путь к файлу как

var path = "C:\\...";

, а затем отправлять содержимое в браузер клиента.

Если файл находится не на локальном компьютере, доступ к нему возможен только через сетевой ресурс. Затем вы можете использовать UNC-пути, например

var path = @"\\Server\Path\...";
8
задан Ace 29 January 2009 в 13:18
поделиться

10 ответов

Если Вы будете подозревать, что у Вас есть проблемы параллелизма при доступе к словарю затем то фиксация не будет иметь применения. Это решит определенную проблему, которую Вы испытываете, однако если у Вас есть параллельный доступ к словарю, Вы собираетесь иметь больше проблем в будущем.

Рассмотрите блокировку доступа к словарю при изменении его.

6
ответ дан 5 December 2019 в 08:54
поделиться

использование примера ng5000, измененного к предложенной стратегии блокировки, дало бы нам:

public static class ThreadSafeDictionary
{
    private static readonly Dictionary<string, int> dict = new Dictionary<string, int>();

    public static void AddItem(string key, int value)
    {
        lock (((IDictionary)dict).SyncRoot)
        {
            if (!dict.ContainsKey(key))
                dict.Add(key, value);
        }
    }
}

наслаждаться...

jimi

Править: обратите внимание, что класс должен быть статичным для понимания этого примера!! ;)

3
ответ дан 5 December 2019 в 08:54
поделиться

Первый код (предполагающий, что типом Словаря является Система. Наборы. Универсальный. Словарь), не скомпилирует. Нет никакой общественности, содержит (ни Содержит метод).

Тем не менее существует возможность, что у Вас могла быть проблема параллелизма. Поскольку Вы подразумевали, что другой поток мог изменить словарь после проверки ContainsKey и перед вставкой. Для исправления этого, оператор блокировки является способом пойти.

Одна точка - я предпочел бы видеть словарь, перенесенный в ориентированный на многопотоковое исполнение класс, что-то как (протесты: не завершенный, и не предназначенный как код ссылки, и может быть улучшен):

public class ThreadSafeDictionary
{
    private Dictionary<string, int> dict = new Dictionary<string, int>();
    private object padlock = new object();

    public void AddItem( string key, int value )
    {
        lock ( padlock )
        {
            if( !dict.ContainsKey( key ) )
                dict.Add( key, value );
        }
    }
}

То, как реализовать ориентированные на многопотоковое исполнение словари, было покрыто полностью здесь.

2
ответ дан 5 December 2019 в 08:54
поделиться

Поскольку Megacan сказал, что Вы могли бы хотеть сфокусироваться на решении любых возможных проблем параллелизма, которые Вы могли бы иметь в своем решении.

Я рекомендую использовать SynchronizedKeyedCollection, хотя это могло бы быть далеко многим факторинг ре для Вас, так как участники для класса не являются тем же те словаря.

2
ответ дан 5 December 2019 в 08:54
поделиться

Трудный сказать, является ли это действительно проблемой параллелизма. Если к словарю получают доступ несколько потоков, то это может действительно быть проблема параллелизма, но я думаю, что необходимо добавить некоторый код трассировки для обнаружения, кто преступник.

Если к словарю получают доступ несколько потоков, то необходимо действительно удостовериться, что Содержание (или ContainsKey) и Добавляет, что методы называют в одной атомарной транзакции. Чтобы сделать это, необходимо действительно назвать эти 2 метода в блокировке.

lock( dict.SyncRoot )
{
   if( dict.Contains( .. ) == false )
      dict.Add ( );
}
1
ответ дан 5 December 2019 в 08:54
поделиться
    lock (((IDictionary)dict).SyncRoot)
    {
        if(!dict.Contains( .. ))
        dict.Add ( );
    }

это работает на меня (см. обновление ng5000 пример ниже), :)

1
ответ дан 5 December 2019 в 08:54
поделиться

Существует ориентированный на многопотоковое исполнение класс словаря, встроенный в Платформу.NET, которая уже предлагает хорошее начало для решения Вашей проблемы, которая могла действительно быть связанным параллелизмом.

Это - абстрактный класс под названием SynchronizedKeyedCollection (K, T), что Вы могли произойти из и добавить метод, который содержит вызов к, Содержит, затем Добавляют в блокировке, которая соединяет основу. SyncRoot.

1
ответ дан 5 December 2019 в 08:54
поделиться

Туз - странный, что это не работало над Вашим кодом, это, конечно, делает согласно примеру (я знаю, что это не помогает Вам, просто любопытство действительно!!).

Надежда Вы разрабатываете его, я уверен, что это будет довольно простая причина сбоя. Вы могли бы даже хотеть попробовать пример вместо своего кода, чтобы видеть, является ли это некоторая другая проблема.

1
ответ дан 5 December 2019 в 08:54
поделиться

Не был должен

if (!evilDict.contains(item.name.ToLower().Trim()))

быть

if (!evilDict.ContainsKey(item.name.ToLower().Trim()))

?

1
ответ дан 5 December 2019 в 08:54
поделиться

Туз,

Создайте новый WindowsFormsApplication (.Net 2.0) и вставьте код в код Form1.cs. (Вам, вероятно, придется изменить имя пространства имен от WindowsFormsApplication1 до что Ваши системные значения по умолчанию к). Кроме того, добавьте кнопку к форме. Так или иначе здесь все это:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private readonly Dictionary<string, int> localDict1 = new Dictionary<string, int>();
        private readonly Dictionary<string, string> localDict2 = new Dictionary<string, string>();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // use two different dictionaries just to show it working with
            // different data types (i.e. we could use class objects too)
            if (localDict1 != null)
            {
                ThreadSafeDictionaryStatic.AddItem(localDict1, "New Item :1", 1);
                ThreadSafeDictionaryStatic.AddItem(localDict1, "New Item :2", 2);
            }
            if (localDict2 != null)
                ThreadSafeDictionaryStatic.AddItem(localDict2, "New Item :1", "this is not a number");
        }
    }

    public static class ThreadSafeDictionaryStatic
    {

        public static void AddItem<T>(IDictionary<string, T> dict, string key, T value)
        {
            if (dict == null) return;
            lock (((IDictionary)dict).SyncRoot)
            {
                if (!dict.ContainsKey(key))
                    dict.Add(key, value);
                else
                {
                    // awful and we'd never ever show a message box in real life - however!!
                    var result = dict[key];
                    MessageBox.Show(String.Format("Key '{0}' is already present with a value of '{1}'", key, result));
                }
            }
        }

        public static T GetItem<T>(IDictionary<string, T> dict, string key)
        {
            if (dict == null) return default(T);
            if (dict.ContainsKey(key))
                return dict[key];
            else
                return default(T);
        }

        public static bool Remove<T>(IDictionary<string, T> dict, string key)
        {
            if (dict == null) return false;
            lock (((IDictionary)dict).SyncRoot)
            {
                if (dict.ContainsKey(key))
                    return dict.Remove(key);
            }
            return false;
        }
    }
}

Сообщите мне, как это идет...

Править: восстановил класс для соответствия сигнатуре метода, также используемые дженерики, поскольку Вы захотите, чтобы метод принял ЛЮБОЙ вид объекта. можно легко возвратить его путем удаления <T> судьи и т.д.

1
ответ дан 5 December 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: