Монитор Ждите кеширования, это хорошая практика?
Я просто написал код, а затем обнаружил, что есть проблема с 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, продолжайте поток, ожидая ответа...
я думаю, что я также должен вернуть ноль, пока кэш обновляется?...
1 ответ
Из MSDN
Если два потока используют Pulse и Wait для взаимодействия, это может привести к тупику.
Так что нет. Ваша реализация не будет лучшей практикой.
Мне кажется, что GetTask должен обновлять кэш в фоновом потоке, затем блокировать вызывающий поток до тех пор, пока кэш не будет обновлен, а затем вернуть первую задачу в соответствии с выбранными критериями.
Поскольку вызывающий поток будет блокировать (ждать) обновление кэша, я не совсем понимаю смысл использования фонового потока в первую очередь. Если цель состоит в том, чтобы предотвратить одновременное обновление кэша несколькими вызывающими потоками, используйте только оператор блокировки (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));