-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);
            }
        }
    }
}

ご覧のとおり、2 つのロックを設定しましたが、そのうちの 1 つは monitor.wait 専用です。スレッドは応答を待機したままにしておいてください...

キャッシュが更新されている間、私もnullを返す必要があると思いますか?...

4

1 に答える 1

2

MSDNから

2 つのスレッドが Pulse と Wait を使用して対話している場合、デッドロックが発生する可能性があります。

いいえ。あなたの実装はベストプラクティスではありません。

GetTask は、バックグラウンド スレッドでキャッシュを更新し、キャッシュが更新されるまで呼び出し元のスレッドをブロックし、選択基準に従って最初のタスクを返すように思われます。

呼び出しスレッドはキャッシュが更新されるのをブロック(待機)するので、そもそもバックグラウンドスレッドを使う意味がよくわかりません。複数の呼び出しスレッドがキャッシュを並行して更新するのを防ぐことが目的の場合は、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));
于 2016-05-25T07:09:16.580 に答える