【问题标题】:My async func inside for loop is not working我的 for 循环内的异步函数不起作用
【发布时间】:2022-01-01 09:02:53
【问题描述】:

我有一个代码可以从数据库中获取所有商品价格,然后调用 API 来更新它们。

由于某种原因,我的 Button1_click 函数内的循环不起作用,但在 Button2_click 上没有循环的类似代码可以正常工作。我不明白为什么。

我可以在输出中看到 API 调用的结果。似乎调用了 API,但价格从未更新。

这是我第一次处理异步函数和任务,所以我是这方面的新手。

    protected async void Button1_Click(object sender, EventArgs e)
    {
        dt = DB_GetItemPrice();

        for (int i = 0; i < dt.Rows.Count; i++)        
        {
            var task = SendRequestAsync(dt.Rows[i]);
            var items = await task;
            Debug.WriteLine(task.Result);
        }            

    }
    protected async void Button2_Click(object sender, EventArgs e)
    {
        dt = DB_GetItemPrice();

        var dr = dt.Rows[0];
        var task = SendRequestAsync(dr);
        var items = await task;
        Debug.WriteLine(task.Result);

    }
    protected DataTable DB_GetItemPrice()
    {
        var db = PSystem.DataHelp.Database.Application;
        var con = new DbConnection(db, ConnectionState.Open);
        var st =
            "SELECT * " +
            "FROM item_discount ";
        var cmd = new PSystem.DataHelp.DbCommand(st, con);

        using (var reader = cmd.ExecuteReader())
        {
            var dt = PSystem.DataHelp.DbManager.GetDataTable(reader);
            if (dt == null || dt.Rows.Count < 1)
                return null;
            return dt;                 
        }
    }

    private async Task<string> SendRequestAsync(DataRow dr)
    {
        string APICall;
        string OrderID = ((long)dr["OrderID"]).ToString();
        string GoodsID = ((long)dr["GoodsID"]).ToString();
        string NewPrice = ((long)dr["NewPrice"]).ToString();
        Debug.WriteLine(OrderID + "  ," + GoodsID + "  ," + NewPrice);
        APICall = "myAPIAdress?" + "&Param0=" + GoodsID  + "," + 3 + "," + NewPrice + "," + 1 + "," + OrderID + ",,";

        using (var wc = new System.Net.WebClient())
        {
            var Message = await wc.DownloadStringTaskAsync(APICall).ConfigureAwait(false);
            return Message;
        }

    } 

【问题讨论】:

  • 循环不是并行的,您需要将这些任务存储在列表或类似的东西中,然后执行Task.WhenAll。比如:var tasks = new List&lt;Task&lt;string&gt;&gt;(); await Tasks.WhenAll(tasks);。您将把任务添加到循环内的列表中,然后在循环外调用Tasks.WhenAll(tasks);。没有保证他们会完成的顺序,它会等到所有任务都完成。
  • 我尝试按照您的建议将所有任务添加到列表中,但仍然没有成功。 protected async void Button1_Click(object sender, EventArgs e) { dt = DB_GetItemPrice(); for (int i = 0; i &lt; dt.Rows.Count; i++) { var task = SendRequestAsync(dt.Rows[i]); activeTasks.Add(task); } await Task.WhenAll(activeTasks); }
  • 您的代码存在一些问题,可能需要先修复,因为它们可能是问题的一部分。就像打开多个连接但从不关闭它们一样。是“myAPIAdress”吗?占位符但不是真正的代码? DB_GetItemPrice 可以返回 null,但您需要一个有效的对象。
  • 我只是不想透露 API 地址。那里还有另一个价值。我确定数据库不会返回 null。我可以看到所有 DataTable 在输出中返回它们的值。 Debug.WriteLine(OrderID + " ," + GoodsID + " ," + NewPrice); 即使这些是导致问题的原因,我的 Button1_Click 也无法正常工作?
  • 异步不是那么容易,我建议你在没有异步的情况下检查你的代码,当功能正常时你迁移到异步

标签: c# asp.net async-await


【解决方案1】:

我认为您的问题是您的 SendRequestAsync 方法中的 ConfigureAwait(false)

尝试删除它。您不应在 UI 同步上下文中使用 ConfigureAwait(false)

Read here for details

【讨论】:

    【解决方案2】:

    发现我的原始代码运行良好。

    我尝试请求的 API 可能有某种速率限制等。当我使用await Task.Delay(1000) 在每个任务之间延迟第二次时,它工作正常。

    【讨论】:

      猜你喜欢
      • 2019-04-07
      • 2015-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多