0

我有一个 Grid 控件,单击每一行都会执行一些后台工作来加载数据。每个后台作业都在线程池线程上执行。当用户快速点击项目时,大量加载数据的请求将排队。我想通过在单击每一行后提供延迟来最小化这种情况。在触发加载数据的请求之前会有一些延迟。

我正在考虑使用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
}

这是解决问题的正确方法吗?

任何建议,将不胜感激!

4

3 回答 3

1

在工作完成之前禁用控件怎么样?或者一旦要执行的作业队列达到一定大小就禁用?这将是防止用户“点击过多”的简单解决方案。这样,延迟将随着您的解决方案的效率/计算机的速度而扩展。

于 2011-05-16T14:42:52.370 回答
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;
        }
     }
 }
于 2011-05-16T15:04:12.003 回答
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);
   ...
}
于 2011-05-16T18:19:23.510 回答