0

这个问题扩展了我之前的一个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)));
}

现在我想取消查询......我可以简单地声明一个CancellactionTokenSourcects,将一个令牌放入一个任务中,然后:

foreach(var item in query)
{
    cts.Token.ThrowIfCancellationRequested();

    Application.Current.Dispatcher.BeginInvoke(
        new Action(() => source.Add(item)));
}

问题是,我只能在出现新结果时取消。因此,如果有一长串项目不符合我的查询条件,我的取消请求将被忽略。

如何将取消加入 LINQ(对象)并能够检查每个项目的取消标记?

4

2 回答 2

1

我不确定,因为我没有测试它......但我认为你可以把它作为你的 linq 查询中的副作用,也许在你的 where 中创建一个方法来这样做,例如:

改变这个:

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 to Objects 会有什么行为(你没有提到你是否使用 linq to sql 或类似的东西)。但这可能行不通。

希望能帮助到你。

于 2013-08-01T12:28:34.307 回答
0

对于我特定于实体框架版本的这个问题:

今天我一直在四处寻找答案,当我终于找到一些东西(我访问的 30 个页面之一)时,这是一个明确的答案(对我来说)问题,特别是针对实体运行的 linq 查询框架。

对于更高版本的实体框架(截至目前),有 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
);
于 2019-09-19T20:04:48.420 回答