用于更新datagrid的线程

时间:2012-01-23 17:24:40

标签: c# wpf multithreading backgroundworker dispatcher

我有一个带有telerik gridview的窗口,我每1分钟更新一次这个gridview。我有一个刷新方法,我称之为每1分钟。

我无法使用BackgroundWorker,因为我的CollectionViewSource位于UI线程中,而后台工作者无法使用它。我的问题是如何从另一个线程调用这个刷新方法?

在某个地方我看到了这个示例代码:

Application.Current.Dispatcher.BeginInvoke(new Action(() => this.Refresh()));

这是我在Refresh_Executed中使用上述代码的真实方式吗? 请帮帮我。

这是我的刷新方法:

public ObservableCollection<RequestView> AllRequestsData { get; set; }

private void Refresh()
    {
        using (ArchiveEntities db = new ArchiveEntities())
        {
            var data = db.RequestSyncs.Where(x => x.UserId == null);
            if (data.Any())
            {
                string IdList = String.Join(",", data.Where(x => x.IsNew).Select(x => x.RequestId));
                if (!String.IsNullOrWhiteSpace(IdList))
                {
                    foreach (var item in db.RequestViews.Where("it.id in {" + IdList + "}"))
                    {
                        this.AllRequestsData.Add(item);
                    }
                }

                foreach (var item in data.Where(x => x.IsDeleted))
                {
                    RequestView rv = this.AllRequestsData.Where(x => x.Id == item.RequestId).SingleOrDefault();
                    if (rv != null)
                    {
                        this.AllRequestsData.Remove(rv);
                    }
                }

                foreach (var item in data)
                {
                    db.RequestSyncs.DeleteObject(item);
                }

                db.SaveChanges();
            }
        }
    }

感谢

3 个答案:

答案 0 :(得分:2)

是的,使用Dispatcher是进行大多数轻型背景工作的正确方法。

但请注意,Dispatcher上的大量后台工作可以锁定UI,因为它仍然在主UI线程上运行。如果您有大量处理,我建议您使用BackgroundWorkerTask Parallel Library或其他形式的多线程(我更喜欢await / async,但这是仅适用于C#5.0或AsyncCTP Refresh

另外,我建议刷新DataGrid绑定的集合而不是DataGrid本身。我认为刷新DataGrid会重新绘制所有UI元素,而刷新ItemsSource只会在可能的情况下重复使用现有的UI元素。

答案 1 :(得分:1)

可能是真正的共同点,但它取决于Refresh方法的内容,你能提供它的内容吗?

修改的 通常我使用异步theads在视图模型中加载数据,而不需要更新RadGridView。但是,例如,当我需要折叠所有组e.t.c时,我使用radGridView.Dispatcher.BeginInvoke(...)。

<强>更新

无需更新RadGridView。您正在更新它的ItemsSource属性。我不建议在这种情况下使用Dispatcher,我会使用Task Parallel Library从数据库接收纯数据并使用与当前UI线程的同步更新ItemsSource

Task.Factory.StartNew<IEnumerable<RequestSyncPlain>>(() =>
{
  return result;
}).ContinueWith(_ =>
{
  try
  {
    _.Wait();
  }
  catch (AggregateException ae)
  {
  }

  foreach (var requestSyncPlain in _.Result)
  {
    var requestSync = new RequestSyncViewModel(requestSyncPlain);

    requestSyncObservableCollection.Add(requestSync);
  }
}, TaskScheduler.FromCurrentSynchronizationContext());

请注意,您应该升级此方法以实现您的需求(您可以将数据库方法放在第一个任务中,并且可以从两个colelctions返回Tuple),这只是想法。

答案 2 :(得分:0)

自.NET 4发布以来,使用TPL是线程化的最佳方式......

using System.Threading.Tasks;
Task.Factory.StartNew(() => this.Refresh())