5

ConcurrentDictionaryに値が追加されるまで待機する必要があるタスクがあります。値が追加された場合、待機を停止して作業を続行する必要があります。タイムアウトが発生した場合(たとえば5秒)も待機を停止する必要があります。

値は別のスレッド/タスクによってConcurrentDictionaryに追加する必要がありますが、コードの性質上、スレッドが相互に通信することは望ましくありません。

これを(C#で)実装するにはどうすればよいですか?

ところで、私はほとんどの部分でスレッドではなくタスクを使用しているので、現在のスレッドでThread.Sleepまたは他のメソッドが適切な決定であるかどうかはわかりません。これは、同じスレッドを使用する他のタスクをスリープさせ、原因となる可能性があるためです。ランダムな問題。

4

3 に答える 3

2

要素がコレクションに追加されるのを「待つ」ことは、一般的に悪いことだと思います。これを行うことは、一般に、スレッドが一定期間ブロックされることを意味します。可能であれば、タイムアウトに対処する必要があります。タイムアウトを検出できない場合は、スレッドを中止して待機を中止する必要があります (スレッドが無期限にブロックされるような状況にはなりたくありません) (キャンセルなど)。

ConcurrentDictionaryそれ自体がスレッドセーフです。ただし、これは、スレッド セーフを使用するすべてのコードを作成するわけではありません。ConcurrentDictionaryオブジェクトを使用する場合は、アプリケーション固有のスレッド セーフ要件を考慮する必要がありConcurrentDictionaryます。 ConcurrentDictionaryそれらのタイプのものを実装することはおそらくできません。ディクショナリに値が追加されたときに行うことも非常に似ています。新しい値の追加時に外部コードを待機または通知するオーバーヘッドにより、ConcurrentDictionary待機またはドンする必要のない使用法であっても、すべての使用法が遅くなります。通知する必要がないため、そのようなことは実装されていません。アプリケーションが値を追加し、値追加されたことを通知する必要があるという事実added はおそらくかなりまれです (辞書の観点からすると、なぜ値を追加しただけだとわかるのでしょ...)。したがって、そのようなアプリケーション固有のことは通常、アプリケーション レベルで行われます。つまり、並行辞書が使用されているという事実は偶然であり、アプリケーションは、別のスレッドが知っておく必要があることを別のスレッドが行ったことを他のスレッドに通知します。これは、 /への呼び出しで辞書インスタンスに追加をラップすることを意味する可能性があり、何かがオーバーライドで待機する可能性があります。または、ディクショナリに値が追加されるたびに発生するイベントを作成するだけの場合もあります。ManualResetEventSlim.ResetSetManualResetEventSlim.Wait

于 2013-01-30T17:12:31.173 に答える
1

ConcurrentDictionaryこのようなものにフックを提供するとは思いません。

これを提供するためにラップまたは派生する可能ConcurrentDictionaryがありますが、そうすることに神経質になります。

ローテクの代わりに、正しい値が見つかるかタイムアウトになるまで、単純にポーリングします。効率の観点からは決して優れた方法ではありませんが、他に問題がなければおそらく最も簡単な方法です。

于 2013-01-30T16:31:58.927 に答える
-1

これが、睡眠ポーリングがどのように機能するかです。速くて汚い。:)

System.Collections.Concurrent.ConcurrentDictionary<string,string> dic = new System.Collections.Concurrent.ConcurrentDictionary<string,string>();

int timeoutCount = 0;
bool hasTimedOut = false;
while (!dic.ContainsKey("KeyYouAreLookingFor"))
{
    //5 minutes has expired
    if (timeoutCount >= 10)
    {
        hasTimedOut = true;
        break;
    }

    //30 second sleep or whatever you want your poll time to be
    System.Threading.Thread.Sleep(30000);
    timeoutCount++;
}

if (hasTimedOut)
{
    //TODO: timeout code
}
else
{
    //TODO: Key has been added
}
于 2013-01-30T16:37:38.213 に答える