5

我有一个任务应该等到一个值被添加到 ConcurrentDictionary。如果添加了值,它应该停止等待并继续其工作。如果发生超时(例如 5 秒),它也应该停止等待。

该值应该由另一个线程/任务添加到 ConcurrentDictionary,但是,由于代码的性质,我不希望线程相互通信。

我应该如何实现这个(在 C# 中)?

顺便说一句,我在大多数情况下使用的是任务,而不是线程,因此我不确定当前线程上的 Thread.Sleep 或其他方法是否是一个好的决定,因为它可能会休眠使用相同线程的其他任务并导致随机问题。

4

3 回答 3

2

我认为“等待”将元素添加到集合中通常是一件坏事。通常,这样做意味着线程被阻塞了一段时间。如果它甚至可能,那么你必须处理超时。如果无法检测到超时,那么您必须处理中止线程以中止等待(您永远不想陷入线程被无限期阻塞的情况),例如取消。

ConcurrentDictionary本身是线程安全的;但这并不能使所有使用ConcurrentDictionary线程安全的代码。ConcurrentDictionary使用对象 时仍需要考虑应用程序特定的线程安全要求。ConcurrentDictionary不可能实现那些类型的东西。将值添加到字典时的操作也非常相似——在添加新值时等待或通知外部代码的开销会导致所有使用的ConcurrentDictionary速度变慢,即使是那些不需要等待或不使用的使用不需要通知——所以这样的事情没有实现。应用程序添加一个值需要通知该值已被通知的事实added 可能非常少见(从字典的角度来看,为什么它会告诉您刚刚添加了一个值......)。因此,这种特定于应用程序的事情通常在应用程序级别完成。即使用并发字典的事实是巧合,您的应用程序通知其他线程另一个线程已经完成了他们需要知道的事情。ManualResetEventSlim.Reset这可能意味着通过调用/来包装添加到字典实例中,并且可以通过覆盖Set来等待。ManualResetEventSlim.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 回答