2011-05-16 122 views
0

我有一個網格控件,並單擊每行做一些後臺作業來加載數據。每個後臺作業都在線程池線程上執行。當用戶快速點擊這些項目時,很多加載數據的請求將排隊。我想通過點擊每一行後提供一個延遲來最小化這一點。在請求加載數據之前會有一些延遲。延遲執行 - C#WPF

我正在考慮使用DispatcherTimer類。類似的,

readonly DispatcherTimer dt = new DispatcherTimer(); 
private void Clicked(object sender, RoutedEventArgs e) 
{ 
    dt.Interval = TimeSpan.FromSeconds(2); 
    dt.Stop(); 
    dt.Start(); 
} 

private void DtOnTick(object sender, EventArgs args) 
{ 
    // Fire a thread and do data loading 
} 

這是解決問題的正確方法嗎?

任何建議,將不勝感激!

+1

我認爲這將是更正確的聚集後臺操作的結果,如有必要,則延遲更新聚合過程中的綁定數據源。問題是你不希望用戶看到很多更新? – Jodrell 2011-05-16 14:29:51

+0

或者是您每次點擊擊中數據庫的問題,並且想要結合各個查詢? – 2011-05-16 14:35:34

+0

後臺工作做了很多COM調用,我不希望這種情況總是發生。 – 2011-05-16 16:08:03

回答

1

如何在作業完成之前禁用控件?或者一旦排隊的工作達到一定的規模就禁用?這將是一個簡單的解決方案,以防止用戶「點擊太多」。這樣,延遲就會隨着您計算機的解決方案/速度的效率而擴展。

1

你試圖做的方式只會將問題本身延遲2秒。所有的點擊都將在兩秒後處理。

您可能會嘗試使用工作線程。比方說,你使用一個隊列,該隊列獲取有關點擊時單擊的每個項目的信息。在創建類時創建的現有線程會在將新項添加到隊列時得到通知。線程獲取第一個項目,處理它,更新UI。如果有更多的項目,則需要下一個項目,處理它,等等。當沒有更多項目時,線程會進入休眠狀態,直到有新項目可用(此處ManualResetEvent將有所幫助)。

的模式將是:

void ItemClicked(...) 
{ 
    lock (WorkQueue) 
    { 
     QueueNewClickItem(...); 
     m_workToDo.Set(); 
    } 
} 


void WorkerThread(...) 
{ 
    bool threadShouldEnd = false; 
    while (!threadShouldEnd) 
    { 
     if (WaitHandle.WaitAny(m_workToDo, m_endThread) == 0) 
     { 
      lock (WorkQueue) 
      { 
       CopyAllPendingWorkItemsToListInThread(); 
       ClearWorkQueue(); 
       m_workToDo.Reset(); 
      } 

      while (!AllLocalItemsProcessed) 
      { 
       ProcessNextWorkItem(); 
      } 
     } 
     else 
     { 
      threadShouldEnd = true; 
     } 
    } 
} 
+0

但並非所有的點擊都被處理。只有最後一次點擊會在指定的延遲後處理。 – 2011-05-16 16:09:10

+0

從你的問題,我認爲你必須處理每一個點擊,但想要一個接一個地處理它們。如果您只想處理最後一次點擊,您應該選擇計時器:點擊發生時,啓動計時器。如果在計時器觸發前發生另一次點擊,請重置計時器。如果定時器觸發,請執行所有點擊所共有的操作。 – 2011-05-17 06:55:45

0

你真正想要做的是這樣的:

private DateTime? _NextAllowedClick; 

private void Clicked(object sender, RoutedEventArgs e) 
{ 
    if (_NextAllowedClick != null && DateTime.Now < _NextAllowedClick) 
    { 
     return; 
    } 
    _NextAllowedClick = DateTime.Now + new TimeSpan(0, 0, 0, 2); 
    ... 
}