在for循环中启动任务,然后对所有这些执行waitall

时间:2014-03-14 02:03:48

标签: c# task-parallel-library

我看到了几个帖子......但是大多数人都在手动创建任务而不是从API接收任务。

我有这段代码

        Task[] tasks = new Task[companyCount];
        // start all threads
        for(int i = 0; i < companyCount; i++) {
            string input = GetNextCompanyRecord(i);
            string token = GetUserToken();
            HttpClient client = GetHttpClient();
            StringContent content = CreateStringContent(input);
            var x = client.PostAsync(companyUrlString, content).ConfigureAwait(continueOnCapturedContext: false);
            tasks[i] = x;
        }
        Task.WaitAll(tasks);

目标是我为for循环中的每条记录启动任务,然后在所有任务开始时......执行一次waitall。

问题是我无法将x变量分配给任务数组。

PostAsync方法没有给我返回任务。相反,它返回ConfiguredTaskAwaitable。但我的希望是我将获得Task,我将能够将其添加到我的阵列中,然后再进行等待。

2 个答案:

答案 0 :(得分:5)

就这样做:

Task<HttpResponseMessage>[] tasks = new Task<HttpResponseMessage>[companyCount];
for(int i = 0; i < companyCount; i++)
{
    string input = GetNextCompanyRecord(i);
    string token = GetUserToken();
    HttpClient client = GetHttpClient();
    StringContent content = CreateStringContent(input);
    var x = client.PostAsync(companyUrlString, content);
    tasks[i] = x;
}
Task.WaitAll(tasks);

但是,也许更清洁的方法是这样做:

var tasks =
    from i in Enumerable.Range(0, companyCount)
    let input = GetNextCompanyRecord(i)
    let token = GetUserToken()
    let client = GetHttpClient()
    let content = CreateStringContent(input)
    select client.PostAsync(companyUrlString, content);

Task.WaitAll(tasks.ToArray());

甚至更好:

using (var client = GetHttpClient())
{
    var tasks =
        from i in Enumerable.Range(0, companyCount)
        let input = GetNextCompanyRecord(i)
        let token = GetUserToken()
        let content = CreateStringContent(input)
        select client.PostAsync(companyUrlString, content);

    Task.WaitAll(tasks.ToArray());
}

答案 1 :(得分:3)

PostAsync 返回Task(确切地说是一个Task<HttpResponseMessage>),但之后您正在调用ConfigureAwait它,返回ConfiguredTaskAwaitable

首先尝试获取对任务的引用,然后调用ConfigureAwait

var task = client.PostAsync(companyUrlString, content);
ConfiguredTaskAwaitable awaitable = task.ConfigureAwait(continueOnCapturedContext: false);
tasks[i] = task;

另外,请考虑:

  • 取消对ConfigureAwait的通话,因为您似乎无论如何都不需要它。
  • 如果您要检索任务,请将您的数组从Task[]更改为Task<HttpResponseMessage>[]。他们完成后的结果。