2016-05-25 5 views
-1

Я только что написал код, а затем я узнал, что есть некоторые проблемы с monitor.wait, заставляя меня выполнять операцию внутри замков, я хотел бы сейчас, если это хороший способ сохранить поток ожидания, ....Монитор Ждите кеширования, ... это хорошая практика?

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

вот мой код:

public static class TaskManager 
{ 
    private static readonly object UpdateLock = new object(); 
    private static readonly object WaitLock = new object(); 

    private static readonly LiaisonDb _db = new LiaisonDb(); 
    private static List<liaQueue> _liaQueueList = new List<liaQueue>(); 
    private static DateTime _lastUpdate = new DateTime(); 

    public static liaQueue GetTask(string sessionType) 
    { 
     liaQueue task; 
     lock (UpdateLock) 
     { 
      if (_lastUpdate < DateTime.Now.AddSeconds(-5)) 
      { 
       Thread t = new Thread(UpdateCache) {IsBackground = true}; 
       t.Start(); 
       lock (WaitLock) 
       { 
        Monitor.Wait(WaitLock); 
       } 

       _lastUpdate = DateTime.Now; 
      } 
      task = _liaQueueList 
       .FirstOrDefault(w => w.Stat == 0 
            && w.Type != null 
            || string.Equals(w.Type, sessionType)); 
     } 
     return task; 
    } 

    private static void UpdateCache() 
    { 
     try 
     { 
      _liaQueueList = _db.liaQueue.Where(w => w.Stat == 0).ToList(); 
     } 
     finally 
     { 
      lock (WaitLock) 
      { 
       Monitor.Pulse(WaitLock); 
      } 
     } 
    } 
} 

Как вы видите, я положил два замка, и один из них только для monitor.wait, держать нить ждет ответа ...

я думаю, что я также должен возвращает нуль, а кэш становится обновилась? ...

+0

Вопросы, требующие помощи по отладке («почему этот код не работает?») Должны включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для воспроизведения в самом вопросе. Вопросы без четкого описания проблемы не полезны другим читателям. См.: Как создать минимальный, полный и проверенный пример. 1 – TomTom

+1

Если ваш код работает - у вас нет технической проблемы, но попросите просмотреть код. – TomTom

+0

@TomTom мой код работает, но вопрос в том, будет ли это работать непрерывно? (мой первый раз с monitor.wait/palse), является способ, которым я реализую его хорошим способом? и что-то вроде этого. Я хочу знать, хорошо ли то, что я сделал, и если это не вызывает проблем, так как оно станет частью сложного приложения. && как запросить проверку кода? – deadManN

ответ

2

От MSDN

Если два потока с помощью Pulse и подождите чтобы взаимодействовать, это может привести к тупиковой ситуации.

Итак, нет. Ваша реализация не будет лучшей практикой.

Мне кажется, что GetTask должен обновлять кеш в фоновом потоке, а затем блокировать вызывающий поток до тех пор, пока кеш не будет обновлен, а затем вернет первую задачу в соответствии с критерием выбора.

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

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

lock (UpdateLock) 
{ 
    if (_lastUpdate < DateTime.Now.AddSeconds(-5)) { 
    Task.Run(() => { 
     _liaQueueList = _db.liaQueue.Where(w => w.Stat == 0).ToList(); 
    }).Wait(); 

    _lastUpdate = DateTime.Now; 
    } 
} 

return _liaQueueList.FirstOrDefault(w => w.Stat == 0 && w.Type != null || string.Equals(w.Type, sessionType)); 
+0

В любом случае, я смотрю на него, и хочу поставить вопрос, хотя я нашел ответ в нем. BTW, используя другую блокировку, мне удалось остановить другой поток от использования импульса ожидания вместе, а другая блокировка - только для требования «синхронного блочного кода» Monitor.wait/pulse, так как импульс ожидания также освобождает блокировку , мне пришлось использовать несколько блокировок, поэтому мой первый замок не будет выпущен, когда я вызову wait(), но поддельный. Так в этом случае, это приемлемо для некоторых других обстоятельств, когда есть необходимость в нескольких потоках? Кстати, спасибо большое. – deadManN

+0

Ваш вопрос заканчивается словами «это хорошая практика?» (заглавие). И ответ на это - нет, потому что вы можете оказаться в тупике. Особенно, если вы используете более одного объекта синхронизации. Резьба 1 может содержать блокировку A, но ждать блокировки B. Резьба 2 может удерживать блокировку B и ждет блокировки A. Итак, ваше решение кажется сложным, и сложность добавляет риск. Путем упрощения решения вы уменьшаете риск. –

+0

Вы правы, но блокировка «A» окружает весь материал, даже блокируя «B», поэтому Thread с блокировкой «B» либо имеет блокировку «A», либо «B» вообще не заблокирован и ждет « A 'then' B ', который должен быть достигнут ... Далее, я могу проверить его с помощью задачи, но мне нужно удалить последнюю задачу, так как некоторые из наших клиентов работают под .net 3.5 и меньше. server 2003, BTW, я помещаю код непосредственно в тело из-за вашего предыдущего предыдущего мнения. если у кого-то есть поток, то с этим кодом, по крайней мере, нет необходимости запускать другой поток. – deadManN