C # работает с синглтоном из двух разных потоков - PullRequest
1 голос
/ 09 июня 2009

Я использую шаблон синглтона в приложении wpf, но сомневаюсь, как заставить его работать с несколькими потоками.

У меня есть класс Monitor, который поддерживает список «настроек» для просмотра для разных «устройств». Схема показана ниже.

В своей основной теме я делаю Monitor.getMonitor.register (список наблюдения) или Monitor.getMonitor.unregister (...) в зависимости от ввода пользователя, и каждые 200 мс выполняется DispatchTimer, который выполняет Monitor.getMonitor.update ()

public class Monitor
{
    private Hashtable Master; //key=device, value=list of settings to watch
    private static Monitor instance = new Monitor();
    private Monitor() {}
    public static Monitor getMonitor() 
    {
        return instance;
    }
    public void register(watchlist){...}
    public void unregister(...){...}
    public void update(){...}

}

register () / unregister () выполнить добавление / удаление в hastable. update () только читает информацию из хеш-таблицы.

В зависимости от количества устройств и настроек, update () будет выполнять итерацию по таблице и ее содержимому, получая последние значения. Основной поток, возможно, вызывает регистрацию и отмену регистрации довольно часто, и я хочу, чтобы графический интерфейс оставался отзывчивым. Какой хороший способ сделать это?

Блокирую ли я хеш-таблицу, добавляю / удаляю и повторяю, ИЛИ просто добавляю итерационную часть в обновление с помощью команды try catch (ах, изящно не удается), чтобы перехватить любое странное состояние, в которое может попасть хеш-таблица (без блокировки) или нет какой-то лучший способ сделать это (если обновление не удастся, все равно будет запущено через 200 мс).

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

Ответы [ 3 ]

11 голосов
/ 09 июня 2009

См. Мою статью о одноэлементных реализациях , чтобы сделать выборку синглтона самой безопасной.

Да, вам необходимо заблокировать, когда вы изменяете или итерацию по хеш-таблице. Вы можете использовать ReaderWriterLock (или, предпочтительно, ReaderWriterLockSlim в .NET 3.5), чтобы разрешить одновременное чтение нескольких читателей. Если вам нужно проделать большую работу во время итерации, вы всегда можете заблокировать, взять копию, разблокировать, а затем поработать с копией - при условии, что работа не против того, чтобы копия была немного устаревшей. *

(Если вы используете .NET 2.0+, я бы предложил использовать общие коллекции, такие как Dictionary<TKey, TValue> вместо Hashtable. Я бы также предложил переименовать ваши методы в соответствии с соглашениями .NET. у кода на данный момент есть явный Java-акцент;)

0 голосов
/ 09 июня 2009

Сколько там строк? Если цикл update () занимает много времени для выполнения итераций, я бы, вероятно, заблокировал. Если основной поток потенциально выполняет много вызовов для регистрации / отмены регистрации, то обновление может несколько раз завершиться сбоем - если оно завершится 20 или 30 последовательными вызовами, это проблема?

Этот код выглядит нормально для меня. Я, вероятно, сделаю класс запечатанным. Я бы также использовал типизированный словарь против Hashtable.

0 голосов
/ 09 июня 2009

Да, вы должны заблокировать каждую операцию:

 public class Monitor
 {
     private Hashtable Master; //key=device, value=list of settings to watch
     ...
     private object tableLock = new object();
     public void register(watchlist) 
     {
         lock(tableLock) {
             // do stuff
         }
     }
 }

Не следует использовать блок try / catch - исключения не следует рассматривать как "нормальную" ситуацию, и вы можете получить состояние поврежденного объекта без каких-либо исключений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...