在后台填充数据网格
我正在尝试在后台填充 devexpress GridControl (这不是一个快速的过程)。我这样做:
...
CreateGrid();
ShowMessageInsteadOfGridControl;
...
FillGrid(dataGrid, other UI params);
...
在网格中写入数据:
private void FillGrid(GridControl data, ...);
{
Task.Factory.StartNew(() =>
{
Application.Current.Dispatcher.Invoke(new Action(() => FillData(gridControl,UIparamns)),
DispatcherPriority.Background);
}).ContinueWith(c => HideUserMessage(UIparamns));
}
当我调用 FillData 时,它会导致 UI 冻结。我无法使用通常的任务,因为网格是从 UI 填充的,并且我有“调用线程无法访问此对象”。
如何在后台进行此类数据发布过程而不冻结 UI?
I'm trying to fill devexpress GridControl in background (it's not quick process). I do it like this:
...
CreateGrid();
ShowMessageInsteadOfGridControl;
...
FillGrid(dataGrid, other UI params);
...
Write data in Grid:
private void FillGrid(GridControl data, ...);
{
Task.Factory.StartNew(() =>
{
Application.Current.Dispatcher.Invoke(new Action(() => FillData(gridControl,UIparamns)),
DispatcherPriority.Background);
}).ContinueWith(c => HideUserMessage(UIparamns));
}
When I call FillData, it causes UI freezing. I can't use usual Task, because Grid filled from UI and I have "The calling thread cannot access this object".
How to make such dataposting process in background without freezing UI?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
调度程序调用将一切放回到 UI 线程上,您需要将操作分成可以在后台完成的部分和真正需要完成的部分UI 线程,就像添加一个项目一样,只将这些操作传递给调度程序。
(
DispatcherPriority.Background
只是意味着其他具有更高优先级的项目将首先执行,这与后台线程无关,每次调用 UI 线程的调度程序都会导致该操作被执行迟早在所述 UI 线程上执行)The dispatcher invoke call puts everything back on the UI thread, you need to split your operation into parts which can be done in the background and those which really need to be done on the UI-thread, like adding an item, only pass those operations to the dispatcher.
(
DispatcherPriority.Background
just means that other items, with higher priority, will be executed first, this has nothing to do with background threads, every call to the dispatcher of the UI-thread leads to that operation being executed on said UI-thread sooner or later)通常,在处理与 UI 线程相关的代码时使用
Task.Factory.StartNew(...)
是危险的,因为它第一次会检查TaskScheduler
,发现没有,就会使用线程池TaskScheduler
。当线程使用名为Compute(3)
的函数完成计算时,它会返回,但在这里它会编组回 UI 线程,然后使用迄今为止的结果更新 UI 线程。第二次和第三次调用 Compute 时,由于 SynchronizationContext 已被编组回 UI,因此它将在 UI 线程上运行,从而阻塞您的 UI。
要避免此潜在问题,请改用
Task.Run(() => A());
有关更多详细信息,请参阅 Stephen Cleary 的文章,网址为 https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html 和/或 Task.Run() 之间有什么区别和 Task.Factory.StartNew()
这是我发现的一种在后台加载数据网格数据而不阻塞 UI 的方法。
首先,创建一个锁对象,并启用集合同步,然后使用 Task.Run() 在后台线程上实际加载数据:
然后在存储库中您可以编写:
然后您可以像这样绑定在关联视图中:
有关详细信息,请参阅:
Generally it is dangerous to use
Task.Factory.StartNew(...)
when working with code related to the UI thread, because the first time it will examine theTaskScheduler
, find that there isn't one, and it will use a thread poolTaskScheduler
. When the thread is done computing using a function called, say,Compute(3)
, it returns but here it marshals back to the UI thread, then will update the UI thread with the results so far.The second and third times it calls Compute, since the SynchronizationContext has been marshaled back to the UI, it will then run on a UI thread, thus blocking your UI.
To avoid this potential problem, instead use
Task.Run(() => A());
For more details, please see Stephen Cleary's article at https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html and/or What is the difference between Task.Run() and Task.Factory.StartNew()
Here is a way that I've found to load data for a datagrid in the background while not blocking your UI.
First, create a lock object, and enable collection synchronization, then actually load the data on a background thread using Task.Run():
Then in your repository you could write:
Then you could bind in your associated view like this:
For details, please see: