Итерация по словарю с foreach l oop и выборка всех пар ключ / значение с элементами подмножества значений - PullRequest
1 голос
/ 15 февраля 2020

У меня есть параллельный словарь, в котором я храню пары ключ / значение. Сложность здесь в том, что значения не являются единичными объектами, такими как строка или целое число, а представляют собой набор элементов, которые добавляются с использованием модели класса. Кажется, глядя на отладку, я могу успешно добавить элементы в словарь, но у меня есть проблема, не зная, как читать эти элементы при переборе словаря из другого потока. Я просто хочу прочитать все пары ключ / значение, включая все элементы, и добавить их в массив, который я могу передать пользователю через JsonResult / Ajax.

Мой класс AlarmEngine:

public static ConcurrentDictionary<string, object> concurrentDictionary = new ConcurrentDictionary<string, object>();

public class Alarm
{
    public int AlarmId { get; set; }
    public string AlarmName { get; set; }
    public string AlarmDescription { get; set; }
    public string ApplicationRoleId { get; set; }
    public DateTime DateTimeActivated { get; set; }
}

Извлечение из метода, в котором я добавляю элементы в словарь:

concurrentDictionary.TryAdd(DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"), new Alarm 
                {
                    DateTimeActivated = DateTime.Now,
                    ApplicationRoleId = applicationRoleId,
                    AlarmId = alarmId,
                    AlarmName = alarmName,
                    AlarmDescription = description,
                }); // I'm using datetime as the key as this is unique form each key/value pair added.

Мой AlarmList MVC Контроллер:

[HttpGet]
public Task<IActionResult> FetchAlarmsListAsync()
{

    // Enumeration is thread-safe in ConcurrentDictionary.
    foreach (var item in AlarmEngine.concurrentDictionary)
    {
        // How do I access the key and value pairs here?
        // Note each value contains a subset of items
        // i want to access all items stored
    }

    return new JsonResult(Array containing all keys and value items);
}

Если лучше прочитать весь словарь и сохранить все ключи / значения (с подэлементами) в списке перед возвратом пользователю в виде массива JSON, это также будет приемлемым решением для меня, просто имейте в виду, что я хочу сделать это как максимально эффективно минимизировать переход из одной формы в другую слишком много раз. Элементы будут добавляться и удаляться в словарь из других потоков, но этот конкретный фрагмент моего приложения, т.е. итерация по словарю, предназначен только для чтения, и для меня не имеет значения, изменилось ли содержимое во время чтения, это просто составить список аварийных сигналов, актуальных / активных на момент запроса.

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Вам нужно хранить данные как правильный класс, не используйте object

public static ConcurrentDictionary<string, Alarm> concurrentDictionary = new ConcurrentDictionary<string, Alarm>();
//                                          ^^^ 

public class Alarm
{
    public int AlarmId { get; set; }
    public string AlarmName { get; set; }
    public string AlarmDescription { get; set; }
    public string ApplicationRoleId { get; set; }
    public DateTime DateTimeActivated { get; set; }
}

Теперь вы можете получить доступ к свойствам тревоги.

// Enumeration is thread-safe in Dictionary.
foreach (var item in AlarmEngine.concurrentDictionary)
{
    Trace.WriteLine(item.Key);  // which is the datetime
    Trace.WriteLine(item.Value.AlarmName);
    // How do I access the key and value pairs here?
    // Note each value contains a subset of items
    // i want to access all items stored
}

Одна вещь, которую вы должны изменить, это не хранить DateTime в виде строки.

public static ConcurrentDictionary<DateTime, Alarm> concurrentDictionary = new ConcurrentDictionary<DateTime, Alarm>();
0 голосов
/ 15 февраля 2020

Если эти ресурсы совместно используются несколькими клиентами / потоками и в основном клиенты читают. Я бы предложил ReaderWriterLockSlim . Это позволяет нескольким читателям и одному писателю.

Таким образом, jsons могут генерироваться параллельно. ConcurrentX - это полезная передача ресурсов другим потокам (например, передача владения) или просто общий доступ данных простого типа.

private static ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();

[HttpGet]
public Task<IActionResult> FetchAlarmsListAsync()
{
    cacheLock.EnterReadLock();
    try
    {
        // Enumeration is thread-safe in Dictionary.
        foreach (var item in AlarmEngine.normalDictionary)
        {
            // How do I access the key and value pairs here?
            // Note each value contains a subset of items
            // i want to access all items stored
        }

        return new JsonResult(Array containing all keys and value items);
    }
    finally
    {
        cacheLock.ExitReadLock();
    }
}

cacheLock.EnterWriteLock();
try
{
    normalDictionary.TryAdd(DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"), new Alarm 
    {
        DateTimeActivated = DateTime.Now,
        ApplicationRoleId = applicationRoleId,
        AlarmId = alarmId,
        AlarmName = alarmName,
        AlarmDescription = description,
    }); // I'm using datetime as the key as this is unique form each key/value pair added.
}
finally
{
    cacheLock.ExitWriteLock();
}

Можно даже кэшировать результат json, когда словарь не изменяется, но вы должны делать это только тогда, когда это проблема.

...