gpt4 book ai didi

c# - 异步绑定(bind)和 LINQ 查询挂起

转载 作者:行者123 更新时间:2023-11-30 12:10:34 25 4
gpt4 key购买 nike

我有一个 UI 控件,它将 Enumerable 作为其绑定(bind)源。但是在我设置绑定(bind)源之前,我必须过滤我原来的 Enumerable。我想为此目的使用 LINQ:

control.BindingSource = from var item in enumerable.Cast<ItemType>()
where item.X == 1
select item;

这是一个 UI 挂起的问题,因为可枚举速度很慢(例如,如果像 yield return new Item(); Thread.Sleep(1000) ... 那样实现)并且控制尝试在界面线程。我试图通过结合使用 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 构造中使用 ObservableCollectionEnumeratorawait 来解决这个问题:

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 不能很好地与 LINQ 配合使用。有一个 Rx 团队试验过的“异步枚举器”,但我相信它已被放弃。

Task-based Asynchronous Pattern确实有一个标准的进度报告方法,您可以在此处使用。

private static void EvaluateItems(IEnumerable<ItemType> items, IProgress<ItemType> progress)
{
if (progress == null)
return;
var query = from var item in items where item.X == 1 select item;
foreach (var result in query)
progress.Report(result);
}


var source = new ObservableCollection<object>();
control.BindingSource = source;
var progress = new Progress<ItemType>(item => source.Add(item));
await Task.Run(() => EvaluateItems(enumerable.Cast<ItemType>(), progress);
基于

IProgress 的代码具有更大的关注点分离。 EvaluateItems 方法只涉及枚举和过滤项目。它不必知道它们将进入 ObservableCollection 或者它正在 WPF 应用程序 (Dispatcher) 中运行。因此它更便于携带和测试。

关于c# - 异步绑定(bind)和 LINQ 查询挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17968516/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com