質問

コードが少しありますが、適切に把握できません。問題は、プログラムがマルチスレッドであり、その中に同期する必要があるコードが少しあるため、私はこれを書いた:

lock (lockObject)
{
   if (!Monitor.TryEnter(lockObject))
     Monitor.Wait(lockObject);

   //do stuff...
   Monitor.PulseAll(lockObject);
}
Monitor.Exit(lockObject);

私が持っている問題は、ある時点ですべてのスレッドがスリープしているように見えることです-誰かが理由を伝えることができますか?プログラムは無限に実行され続け、CPUをほとんど消費しませんが、作業は行われません。プログラムをトレースすると、ある時点でスレッドはアクティブではなく、多くのスレッドがスリープしていることがわかりました。ほとんどの場合、エラーは(開発者の場合-常に)モニターの前に0.5mあります-しかし、私は自分でそれを把握できません...たぶん数分で;)

誰かに説明してください-事前に感謝します。

役に立ちましたか?

解決

LockObject lockObject に違いはありますか?明確ではありません...

しかし!それらが異なるオブジェクトである場合、最初に:持っていないロックを Wait することはできません... TryEnter は、タイムアウト。そのコードは何をしようとしているのですか?

コンテキストがなければ、 PulseAll および Wait が何をするように設計されているかは完全には明らかではありません。たとえば、こちらは、次の場合にキューをブロックするために使用されます。いっぱいです( Wait )、またはスペースが使用可能になったときに解放します( PulseAll )など。スレッド間の完全な相互作用なしにスレッドコードをデバッグするのは困難です。

必要なだけのように聞こえます:

lock (lockObject)
{
    // do stuff
}

すぐにわかる問題が2つあります。まず、取得したロックを常に解放することは明らかではありません(例外)。 Enter / Exit lock を使用してみてください-正しくなります。

2番目;すべてのスレッドが Wait を呼び出した場合...誰がそれらを起動しますか?彼らは何を待っていますか? ?提示されているとおり:はい、すべて無期限にスリープします。

他のヒント

最初のロック文はタイプミスであり、lock(lockObject)(小文字)を意味すると思います。

ここでロックを少し誤解していると思います。コード内のifブロックは真実ではありません。理由は、lock(lockObject)が実際に次のように展開されるからです

Monitor.Enter(lockObject);
try {
...
} finally{ 
Monitor.Exit(lockObject);

したがって、ifブロックを押すまでに、すでにロックを所有しているので、TryEnterが常に成功するはずです。

これは奇妙な設定です。 「LockObject」は「lockObject」と同じですか?それともタイプミスですか?それらが同じ場合、すでにロックしているものに対してMonitor.TryEnterを呼び出す必要がないため、セットアップは冗長です。 「LockObject」が別のオブジェクトである場合、Monitor.Exitをロックステートメント内に移動してみませんか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top