【问题标题】:Await or timeout on an asynchronous operation异步操作等待或超时
【发布时间】:2015-02-15 20:33:53
【问题描述】:

请看下面我的代码

HttpResponseMessage messge = client.GetAsync("ladders/get/"+ID+").Result;
if (messge.IsSuccessStatusCode)
{
   string result = messge.Content.ReadAsStringAsync().Result;
}

我需要执行此代码,直到“结果”变量不为空或最多 30 分钟。每分钟将在 30 分钟内执行以下代码,直到 (result !=null)。

HttpResponseMessage messge = client.GetAsync("ladders/get/"+ID+").Result;

让我们看看,如果在 30 分钟内没有得到“结果”值,那么 30 分钟后功能将自动停止并通知用户未找到该值。同时用户可以访问其他页面。

请建议我如何解决这个问题.....

【问题讨论】:

  • 考虑在此处使用计时器。间隔为 1 分钟,如果达到 30 分钟或得到结果,则取消计时器。有关您的选择,请参阅stackoverflow.com/questions/1416803/…。我会为您推荐 System.Threading.Timer 。另请注意,如果您的滴答处理程序花费的时间过长,计时器滴答事件可能会重叠。
  • 如果我们谈论的是 Web 开发,那么请考虑使用 setTimeout/setInterval 之类的方法执行上述逻辑,每分钟轮询一次 Web 服务器。

标签: c# asp.net multithreading asynchronous async-await


【解决方案1】:

我首先建议您不要使用.Result 进行屏蔽。 HttpClient 公开的 API 本质上是异步的。通过使用它,您可能会在您的代码中引入您可能不想要的死锁。

基本上,您要实现的是“第一个任务获胜”操作。为此,由于HttpClient.GetAsync 已经返回了Task,您可以向它执行另一个使用Task.Delay 的任务,该Task.Delay 在内部使用计时器。而且,无论哪个任务先完成,您都会await

public async Task GetAsync()
{
    var expirationTimeTask = Task.Delay(TimeSpan.FromMinutes(30));
    var responseTask = client.GetAsync("ladders/get/ " + ID);

    var finishedTask = await Task.WhenAny(expirationTimeTask, responseTask);
    if (finishedTask == expirationTimeTask)
    {
        // If we get here, the timer passed 30 minutes
    }
    else
    {
        // If we get here, we got a response message first.
        if (responseTask.IsSuccessStatusCode)
        {
            string result = await responseTask.Content.ReadAsStringAsync();
        }   
    }
}

【讨论】:

  • 您还可以将CancellationToken 传递给GetAsync,当expirationTimeTask 首先完成时,您可以取消它。
  • @Jasd 你是对的。但是OP似乎不需要它。但它可以很容易地添加。
猜你喜欢
  • 2016-09-04
  • 1970-01-01
  • 2018-07-13
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多