Monitor 等待缓存,...这是一个好习惯吗?
Monitor Wait for caching,... it this a good practice?
我刚刚写了一个代码,然后我发现 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,让线程等待答案...
我想我还必须 returns 在缓存刷新时为空?...
来自MSDN
If two threads are using Pulse and Wait to interact, this could result in a deadlock.
所以,没有。您的实施不是最佳实践。
在我看来,GetTask 应该在后台线程上更新缓存,然后阻塞调用线程直到缓存被更新,然后 return 第一个任务根据 select 标准。
由于调用线程会阻塞(等待)缓存更新,所以我一开始不太明白使用后台线程的意义。
如果目的是防止多个调用线程并行更新缓存,只需使用 lock(UpdateLock) 语句。
如果您确实想要 运行 后台线程上的缓存(并等待),请考虑改用 Task 库。但是我真的不明白它的意义。
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));
我刚刚写了一个代码,然后我发现 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,让线程等待答案...
我想我还必须 returns 在缓存刷新时为空?...
来自MSDN
If two threads are using Pulse and Wait to interact, this could result in a deadlock.
所以,没有。您的实施不是最佳实践。
在我看来,GetTask 应该在后台线程上更新缓存,然后阻塞调用线程直到缓存被更新,然后 return 第一个任务根据 select 标准。
由于调用线程会阻塞(等待)缓存更新,所以我一开始不太明白使用后台线程的意义。 如果目的是防止多个调用线程并行更新缓存,只需使用 lock(UpdateLock) 语句。
如果您确实想要 运行 后台线程上的缓存(并等待),请考虑改用 Task 库。但是我真的不明白它的意义。
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));