首页 > 解决方案 > Task.Run 有时会返回两次

问题描述

我有一个从斜杠命令调用的天蓝色函数应用程序。有时该函数需要一些时间来返回请求的数据,所以我让该函数返回一个“正在计算...”消息以立即松弛,并在 Task.Run 上运行实际处理(请求包含我发布的 webhook回到我最终得到数据的时候):

Task.Run(() => opsData.GenerateQuoteCheckMessage(incomingData, context.FunctionAppDirectory, log));

这工作得很好,除了人们不时地从 slack 调用函数时,它会返回两次数据。因此它将显示一条“正在计算...”消息,然后从上述函数返回 2 个结果。

顺便说一句,Azure 函数以:public static async Task 开头

谢谢!

更新:这是函数的代码:

    [FunctionName("QuoteCheck")]
     public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequestMessage req, TraceWriter log, ExecutionContext context)
     {
          var opsHelper = new OpsHelper();

          string bodyContent = await req.Content.ReadAsStringAsync();
          var parsedBody = HttpUtility.ParseQueryString(bodyContent);
          var commandName = parsedBody["command"];
          var incomingBrandId = parsedBody["text"];
          int.TryParse(incomingBrandId, out var brandId);
          var responseUrl = parsedBody["response_url"];

          var incomingData = new IncomingSlackRequestModel
          {
               UserName = parsedBody["user_name"],
               ChannelName = parsedBody["channel_name"],
               CommandName = commandName,
               ResponseUri = new Uri(responseUrl),
               BrandId = brandId
          };

          var opsData = OpsDataFactory.GetOpsData(context.FunctionAppDirectory, environment);

          Task.Run(() => opsData.GenerateQuoteCheckMessage(incomingData, context.FunctionAppDirectory, log));

          // Generate a "Calculating" response message based on the correct parameters being passed
          var calculatingMessage = opsHelper.GenerateCalculatingMessage(incomingData);

          // Return calculating message
          return req.CreateResponse(HttpStatusCode.OK, calculatingMessage, JsonMediaTypeFormatter.DefaultMediaType);
      }
 }

然后 GenerateQuoteCheckMessage 计算一些数据并最终发回 slack (Using Rest Sharp) :

    var client = new RestClient(responseUri);
    var request = new RestRequest(Method.POST);
    request.AddParameter("application/json; charset=utf-8", JsonConvert.SerializeObject(outgoingMessage), ParameterType.RequestBody);

    client.Execute(request);

标签: c#asynchronousasync-awaitazure-functionsslack

解决方案


使用 Kzrystof 的建议,我在发布到队列的函数中添加了一个服务总线调用,并添加了另一个函数来读取该队列并处理请求,响应 slack 给我的 webhook:

public void DeferProcessingToServiceBus(IncomingSlackRequestModel incomingSlackRequestModel)
{
    var serializedModel = JsonConvert.SerializeObject(incomingSlackRequestModel);
    var sbConnectionString = ConfigurationManager.AppSettings.Get("SERVICE_BUS_CONNECTION_STRING");
    var sbQueueName = ConfigurationManager.AppSettings.Get("OpsNotificationsQueueName");
    var client = QueueClient.CreateFromConnectionString(sbConnectionString, sbQueueName);
    var brokeredMessage = new BrokeredMessage(serializedModel);
    client.Send(brokeredMessage);
}

推荐阅读