如何在不等待c#.Net 4.5.1中的方法响应的情况下迭代调用方法?

时间:2014-01-10 00:27:22

标签: c# .net .net-4.5

首先,我为这个问题的可怕措辞道歉...这是情景:

我构建了一个WEB API方法,该方法接收ProductID,然后将该产品图像上传到Amazon S3。这部分工作正常。

我现在正在尝试运行一个控制台应用程序,它将获取一系列ProductID并循环遍历它们,调用API方法,而不是等待结果......

有人能指出我正确的方向吗?

我想另一个警告是不要吃掉运行控制台应用程序的机器上的所有资源...所以也许是线程上限?

UPDATE(这似乎仍然是同步的):

class Program
{
    async static void DoUpload(int itemid)
    {
        Console.WriteLine("Starting #:" + itemid);
        Thread.Sleep(2000); //Simulates long call to API
        Console.WriteLine("Finishing #:" + itemid);
    }
    static void Main(string[] args)
    {
        for (int i = 0; i < 20; i++)
        {
            DoUpload(i);
        }
    }
}

2 个答案:

答案 0 :(得分:2)

有几种简单的方法可以做到这一点。

我建议使用Parallels。它可以最优化地使用您的环境中的许多线程/核心。对于您的示例,您只需执行以下操作:

var status = Parallel.For(0, 20, DoUpload);

while (!status.IsCompleted)
{
    //Do something while you wait
}

另一种方法是使用Tasks,并将每个调用作为单独的任务发送。但请注意这种方法,因为如果迭代次数太多,可能会使系统超载待处理的任务。

List<Tasks> tasks = new List<Tasks>();

for (int i = 0; i < 20; i++)
{
    var task = Task.Run(() => DoUpload(i));

    tasks.Add(task);
}

//wait for completion of all tasks
Task.WaitAll(tasks.ToArray());

答案 1 :(得分:-1)

我不建议使用Parallel.For。它没有给出令人满意的并行控制(你可能不想敲除将开始超时的请求的hundrades),它也需要不必要的上下文切换。

线程/核心不是http请求的限制因素。

在示例中更改

Thread.Sleep(2000)

await Task.Delay(2000)

使用真正的网络API呼叫时

await httpClient.PostAsync(...)

还记得在Main等待

Console.ReadLine() // or something more sophisticated

否则程序将在拨打电话之前终止。

然后,为了控制并行度,我认为最简单的解决方案是使用信号量来计算未完成调用的数量,在主循环中等待信号量在发出新请求之前再次发出信号。