【发布时间】:2013-07-31 20:50:39
【问题描述】:
我有一个将Enumerable 作为其绑定源的UI 控件。但是在我设置绑定源之前,我必须过滤我原来的Enumerable。我想为此目的使用 LINQ:
control.BindingSource = from var item in enumerable.Cast<ItemType>()
where item.X == 1
select item;
这是一个 UI 挂起的问题,因为 enumerable 很慢(例如,如果像 yield return new Item(); Thread.Sleep(1000) ... 那样实现)并且控制尝试在 UI 线程中执行查询。我试图通过结合使用 Task 和 async-await 来解决这个问题:
control.BindingSource = await Task.Factory.StartNew(() =>
(from var item in enumerable.Cast<ItemType>()
where item.X == 1
select item).ToArray());
现在 UI 不会挂起,但查询执行完成后结果会立即可见。我通过在while 构造中使用ObservableCollection 和Enumerator 和await 来解决这个问题:
var source = new ObservableCollection<object>();
control.BindingSource = source;
var enumerator = enumerable.GetEnumerator();
while (await Task.Factory.StartNew(() => enumerator.MoveNext()))
{
var item = (ItemType)enumerator.Current;
if (item.X == 1)
source.Add(item);
}
我正在寻找至少允许使用 LINQ 的解决方案。 有什么想法吗?
【问题讨论】:
-
在
async代码中,您应该更喜欢Task.Run而不是StartNew; here's why.
标签: c# multithreading linq user-interface async-await