【问题标题】:Task is not running asynchronously任务未异步运行
【发布时间】:2018-09-12 19:16:55
【问题描述】:

我已经在Task.Run 中封装了这个动作,但似乎我遗漏了一些非常基本的东西。但是想不通。

public void SaveOrderList(List<Order> inputList)
{
    Dictionary<string, string> result = new Dictionary<string, string>();
    string code = string.Empty;
    Task.Run(() =>
    {
        foreach (var item in inputList)
        {
            code = CreateSingleOrder(item);
            result.Add(item.TicketNumber, code);
        }

        ////TODO: Write logic to send mail
        emailSender.SendEmail("abc@xyz.com");
    });
}

由于inputList 中可能有许多条目,并且每个条目可能需要 5 秒的时间来处理,所以我不希望最终用户阻止 UI。相反,我会发送一封邮件并通知有多少处理成功,哪些处理失败。

要实现这一点,我最清楚的是Task.Run。但是,问题是一旦函数完成,我看不到 foreach 循环中的代码曾经工作过,因为它从来没有进入数据库。

谁能帮我找出我在这里缺少什么。

仅供参考,此函数是从 Web API 调用的,而 Web API POST 方法是从 javascript 调用的。下面是 Web API 端点的代码。

[HttpPost, Route("SaveOrderList")]
[ResponseType(typeof(bool))]
public IHttpActionResult SaveOrderList(List<Order> orderList)
{
     orderManagerService.SaveOrderList(orderList)
     return this.Ok();
}

提前感谢您的帮助。

【问题讨论】:

  • 第一个建议是运行带有调试器的程序,在 foreach 循环中的行上放置一个断点,看看会发生什么。如果您的调试器在整个 lambda 表达式而不是单个行上放置断点,则将 foreach 循环移至其自己的方法中,这不会成为问题
  • 您不应该在 Web 上实现运行后忘记代码。没有人会保证在响应发送给客户端后进程不会被杀死。
  • @LordWilmore 当我将调试器放入 foreach 循环中时,一切正常。列表中的所有条目一一执行,然后 emailSender 被正确调用。当我删除应用程序中的所有断点时,似乎没有任何效果。
  • @hardkoded 有没有办法处理 UI 不应因长时间任务而被阻塞的情况?我想我可以在 task.run 中放一个 try catch,这样如果有任何错误,我会阅读字典并找出在引发此异常之前执行了多少次。
  • 好吧,你正在创建一个即发即弃的任务,它不应该等到任务完成。当您完全不知道代码是否正确传递时,您也会返回 200 OK

标签: c# asp.net-web-api async-await task-parallel-library


【解决方案1】:

您需要仔细考虑其工作原理。本文有几点建议:

https://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html

但我要指出,在 Web 应用程序上“一劳永逸”通常是错误的方法。

对于您的示例,您真的想考虑您的用户体验 - 如果我在您的网站上下订单,但过了一段时间才发现订单失败(通过电子邮件,我可能不会检查),我会不要太感动。最好等待保存结果,或者对单个订单项发出多个 API 请求,并在前端显示成功订单的增量结果。

我还建议仔细研究一下为什么您的订单保存速度如此之慢 - 这将继续对您造成问题,直到它更快为止。

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多