【问题标题】:Async/Await how to handle with "old" results?Async/Await 如何处理“旧”结果?
【发布时间】:2015-04-21 09:56:36
【问题描述】:

我有一个异步加载函数来调用 WCF 服务,然后对结果进行一些处理。

protected async void Load(bool reload)
{
     var items = await GetItems(skip, take, SearchString);

     OnItemsLoaded(items);
}

即使旧的加载没有完成,也可以多次调用加载。

示例: 调用 1 => 调用 2 => 调用 2 的结果 => 调用 1 的结果

这就是我使用TaskContinueWith 来检查线程ID 并丢弃“旧”结果的原因。 但我想将其更改为 Async/Await 模式。

有两种情况:

  1. Reload 为真:应丢弃所有旧线程/结果。只应处理“最新”结果。
  2. Reload 为假:应处理所有线程/结果。

【问题讨论】:

  • 你可以等待一个 GetItems 元组和一个序列号,可能使用互锁的东西分配(并允许溢出!)或者你可以将一个序列号传递给 GetItems 并让它在一个结构中返回它与物品的集合?

标签: c# multithreading wcf asynchronous async-await


【解决方案1】:

你想要的可以通过CancellationTokenCancellationTokenSource实现的合作取消机制来实现。

您需要做的是将令牌传递给您的方法,并在工作时监视该令牌。如果用户请求取消,您就取消操作。

private CancellationTokenSource cts = new CancellationTokenSource();
protected async Task LoadAsync(bool reload)
{
     if (reload)
     {
        cts.Cancel();
     }

     var items = await GetItems(cts.Token, skip, take, SearchString);
     OnItemsLoaded(items);
}

在您的 GetItems 方法中,您需要监视该令牌:

public async Task GetItemsAsync(CancellationToken cancellationToken)
{
   while (!cancellationToken.IsCancellationRequested)
   {
      // Do some work.
   }

   // This will cause the task to transfer to a cancelled state, if needed.
   cancellationToken.ThrowIfCancellationRequested();     
}

请注意,我将 LoadAsync 更改为返回 async Task 而不是 async void。后者仅适用于顶级事件处理程序。

【讨论】:

  • 感谢您的评论。我无法更改 GetItems 中的任何内容。问题是如何确定它是否应该取消 Call1、Call2 等...我的想法是检查等待返回时是否有更新的上下文,然后决定要做什么。也许有可能使用SynchronizationContext
猜你喜欢
  • 2018-09-03
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
相关资源
最近更新 更多