簡體   English   中英

如何在給定時間處理(動態添加)項目?

[英]How to process (dynamically added) items at a given time?

我有一個(並發的)優先級隊列,其中以時間戳記(將來)為鍵,並在達到時間作為值時應調用一個函數(/應該處理的項目)。 我不想將計時器附加到每個項目上,因為那里有很多計時器。 我寧願使用調度程序線程/任務。

這樣做的好策略是什么?


使用運行調度程序的線程...(后接偽代碼)

// scheduler
readonly object _threadLock = new object();
while (true)
{
    if(queue.Empty) 
    {
        Monitor.Wait(_threadLock);
    } 
    else 
    {
        var time = GetWaitingTimeForNextElement();

        if(time > 0)
          Monitor.Wait(_threadLock, time);
        else
          // dequeue and process element
    }  
}

...並在添加元素(到空隊列或添加新的第一個元素)時發出脈沖?

// element enqueued 
Monitor.Pulse(_threadLock);

還是以某種方式使用Task.Delay(int, CancellationToken )鏈接( Task.ContinueWith(...) )任務? 如果新的第一個元素入隊,這將需要一些邏輯來中止等待,或者如果沒有人在運行,則需要創建新任務。 感覺有一個更簡單的解決方案,我現在沒有。 :)


或使用計時器(非常偽代碼,僅是為了了解這一點)...

System.Timers.Timer x = new System.Timers.Timer().Start();

x.Elapsed += (sender, args) =>
{
    // dequeue and process item(s)

    x.Interval = GetWaitingTimeForNextElement(); // does this reset the timer anyway?
}

...並在添加元素時更新間隔(如上)。

// element enqueued 
x.Interval = updatedTime;

我還擔心等待方法/計時器的精度:毫秒相當粗略(盡管可能可行)是否有更好的選擇?

人機工程學...

多數民眾贊成再次有很多問題/想法-對此表示抱歉-但有太多選擇和擔憂,因此難以一概而論。 總結一下: 為動態進入的項目實施(精確)時間計划系統的最佳方法是什么?

我感謝所有提示和答案! 非常感謝。

我建議這樣做:

  1. 創建一個名為TimedItemsConcurrentPriorityQueue<TKey, TValue>的類,該類繼承自ConcurrentPriorityQueue<TKey, TValue>

  2. 在您的TimedItemsConcurrentPriorityQueue<TKey, TValue>類中實現一個名為ItemReady的事件,該事件會在根據時間戳記准備就緒(待處理)時觸發。 您可以使用單個計時器,並根據需要通過遮蔽EnqueueInsertRemove和其他方法(或通過修改ConcurrentPriorityQueue<TKey, TValue>的來源並使這些方法成為虛擬的以便可以覆蓋它們)來根據需要更新計時器。

  3. 實例化TimedItemsConcurrentPriorityQueue<TKey, TValue>的單個實例,讓我們將其稱為變量itemsWaitingToBecomeReady。

  4. 實例化BlockingCollection<T>的單個對象,讓我們將其稱為變量itemsReady。 使用采用IProducerConsumerCollection<T>構造函數,並將其傳遞給ConcurrentPriorityQueue<TKey, TValue>的新實例(它繼承IProducerConsumerCollection<KeyValuePair<TKey,TValue>>

  5. 每當在itemsWaitingToBecomeReady中觸發事件ItemReady時,您就將該條目出隊,並將其排隊到itemsReady。

  6. 使用BlockingCollection<T>.GetConsumingEnumerable方法並使用類似以下的新任務來處理itemsReady中的項目:

Task.Factory.StartNew(() =>
{
  foreach (var item in itemsReady.GetConsumingEnumerable())
  {
    ...
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM