-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,让线程等待答案...

我想我还必须在缓存刷新时返回null?...

4

1 回答 1

2

来自MSDN

如果两个线程正在使用 Pulse 和 Wait 进行交互,这可能会导致死锁。

所以不行。您的实施不会是最佳实践。

在我看来,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));
于 2016-05-25T07:09:16.580 回答