首先,我为这个问题的糟糕措辞道歉......场景如下:
我构建了一个 WEB API 方法,该方法接收 ProductID,然后将该产品图像上传到 Amazon S3。这部分工作得很好。
我现在正在尝试运行一个控制台应用程序,该应用程序将获取一系列 ProductID 并循环遍历它们,调用 API 方法,而不是等待结果......
谁能指出我正确的方向?
我想另一个警告是不要占用运行控制台应用程序的计算机上的所有资源......所以也许是线帽?
更新(这似乎仍然是同步的):
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);
}
}
}
有几种简单的方法可以做到这一点。
我建议使用 Parallels。 它可以最优化地利用您的环境许多线程/内核。 对于您的示例,您只需执行以下操作:
var status = Parallel.For(0, 20, DoUpload);
while (!status.IsCompleted)
{
//Do something while you wait
}
另一种方法是使用任务,并将每个调用作为单独的任务发送。 但是,使用此方法时要小心,因为如果迭代次数过多,则可能会使系统过载。
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());
我不建议使用Parallel.For。它不能提供令人满意的并行性控制(您可能不想敲打大量将开始超时的请求),还需要不必要的上下文切换。
线程/内核不是 http 请求的限制因素。
在示例中更改
Thread.Sleep(2000)
自
await Task.Delay(2000)
以及使用真实 Web API 调用时
await httpClient.PostAsync(...)
还记得在主楼等待
Console.ReadLine() // or something more sophisticated
否则,程序将在调用之前终止。
然后,为了控制并行级别,我认为最简单的解决方案是使用信号量来计算未完成调用的数量,在发出新请求之前在主循环中等待信号量再次发出信号。