我有一个带有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();
}
}
}
感谢
答案 0 :(得分:2)
是的,使用Dispatcher
是进行大多数轻型背景工作的正确方法。
但请注意,Dispatcher
上的大量后台工作可以锁定UI,因为它仍然在主UI线程上运行。如果您有大量处理,我建议您使用BackgroundWorker
,Task 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())