【问题标题】:List<Tasks> dont do anything when i run code but if i step through it worksList<Tasks> 在我运行代码时不做任何事情,但如果我单步执行它就可以了
【发布时间】:2019-05-30 20:33:38
【问题描述】:

当我执行代码时,在WhenAll 之后检查idList 是空的,如果我在WhenAll 之后使用断点单步执行它,一切都会按预期工作。

此代码在非异步方法中。

就好像让它自己运行并不是启动任务。

var currentPage = 1;
List<Result> idList = new List<Result>();

var response = this.GetDocuments(currentPage).Result;
//idList.AddRange(response.results);

var tasks = new List<Task>();

for (var i = 0; i < response.meta.page.total_pages; ++i)
{
    var t = new Task(() =>
    {
        response = this.GetDocuments(i+1).Result;
        idList.AddRange(response.results);
    });
    tasks.Add(t);
    t.Start();
}

 Task.WhenAll(tasks).Wait();

 public async Task<ResponseObject> GetDocuments(int currentPage)
        {
            var result = await httpClient.GetAsync($"api/as/v1/engines/urlname/documents/list?page[current]={currentPage}").ConfigureAwait(false);

            if (!result.IsSuccessStatusCode)
            {
                loggly.Error($"Exception: ScheduledJobBase, IndexPages, failed when getting documents from Swiftype, response: { result }");
                return null;
            }

            return await result.Content.ReadAsAsync<ResponseObject>().ConfigureAwait(false); ;
        }

【问题讨论】:

  • 表达式Task.WhenAll(tasks).ConfigureAwait(false)返回一个Task,你需要await它(或者在非异步方法中调用.Wait())。
  • Task.WhenAll not waiting的可能重复
  • 您还将循环变量 (i) 传递到创建闭包的任务的 lambda 中,因此您的 GetDocuments 调用 可能 对 @987654333 使用错误的值@。为了解决这个问题,您可以在创建任务之前创建一个中间变量。喜欢var i1 = i; ... GetDocuments(i1+1) ...
  • 你可以从这个answer开始
  • 还有一点——正如@Hakit01 提到的,从多个线程访问非并发集合可能会导致很多讨厌的错误。因此,您可以使用并发集合(System.Collections.Concurrent 命名空间),或者在您的情况下,我会完全避免使用集合。 Task.WhenAll 创建一个任务,返回底层任务的所有结果,因此从任务中返回一个值,然后将它们聚合到一个集合中可以解决问题。此外,您无需手动创建任务 - 只需从您放入任务构造函数的 lambda 中提取一个异步方法即可。

标签: c# .net asynchronous task


【解决方案1】:

发生的问题可能是由于集合不同步,可能抛出了 InvalidAccessException。

【讨论】:

【解决方案2】:

虽然理想的方案是将方法返回类型转换为Task 并返回或等待Task.WhenAll 的结果,但如果方法必须保持非异步,则调用.Wait() 的结果Task.WhenAll 像这样打电话:

Task.WhenAll(tasks).Wait();

【讨论】:

  • 我做了这个更改,但它并没有解决我的问题:/,并且 ConfigureAwait 不包含等待方法?。
  • 只需在 Task.WhenAll() 上致电.Wait()(我已更新答案以反映这一点)。如果您不使用 async/await,则不需要 ConfigureAwait。
猜你喜欢
  • 2022-01-19
  • 2017-12-05
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多