这个问题扩展了我之前的Asynchronuos binding and LINQ query hangs。假设我有一个像我们这样的LINQ:
var query = from var item in items where item.X == 1 select item;
我可以异步遍历query
并将每个项目分发到UI(或者我可以使用IProgress
):
foreach(var item in query)
{
Application.Current.Dispatcher.BeginInvoke(
new Action(() => source.Add(item)));
}
现在我想取消查询...我可以简单地声明一个CancellactionTokenSource
cts,将一个令牌放入任务然后:
foreach(var item in query)
{
cts.Token.ThrowIfCancellationRequested();
Application.Current.Dispatcher.BeginInvoke(
new Action(() => source.Add(item)));
}
麻烦的是,我只有在出现新结果时才能取消。因此,如果有一长串项目不符合我的查询条件,我的取消请求将被忽略。
如何将取消纳入LINQ(对象)并能够检查每个项目的取消令牌?
答案 0 :(得分:1)
我不确定,因为我没有测试它...但我认为你可以把它作为副作用放在你的linq查询中,也许在你的位置创建一个方法,例如:
改变这个:
var query = from var item in items where item.X == 1 select item;
要:
var query = from var item in items where CancelIfRequestedPredicate(item,i=>i.X == 1) select item;
并创建一个方法:
private bool CancelIfRequestedPredicate<T>(T item,Predicate<T> predicate)
{
cts.Token.ThrowIfCancellationRequested();
return predicate(item);
}
由于linq使用延迟执行,我认为它将在每次迭代时运行您的方法。
就像观察一样,我不知道如果你没有使用Linq到对象会有什么行为(你没有提到你是否正在使用linq到sql,或类似的东西)。但它可能不起作用。
希望它有所帮助。
答案 1 :(得分:0)
对于我这个问题的特定于Entity Framework版本:
当我终于找到了一个明确的答案(对我来说)时,我一直在努力寻找答案,直到找到答案(我访问过的30页网页之一)。 这个问题特别是针对实体框架运行的linq查询。
对于更高版本的Entity Framework(截至目前) 有一些ToListAsync扩展方法,其中包括带有取消令牌的重载。
与任务(在我的情况下,我的查询是在任务中)一样,我也在其中运行了查询,但这是我最关心的数据查询。
var sourceToken = new System.Threading.CancellationTokenSource();
var t2 = System.Threading.Tasks.Task.Run(() =>
{
var token = sourceToken.Token;
return context.myTable.Where(s => s.Price == "Right").Select(i => i.ItemName).ToListAsync(token);
}
, sourceToken.Token
);