我最近开始用C#(在对PHP和JavaScript有了一些经验之后)编程,我构建了一个简单的控制台程序,可以下载JSON字符串并将某些值存储在数据库中。有问题的数据大约是70000集(转换成行到我的数据库中)。由于从(Quandl)下载此JSON的服务器的限制,建议每个请求下载100个数据集,因此我有700个请求。
对于每个请求,我下载JSON字符串,对其进行反序列化并循环100次,以将相应的值存储在数据库中。我使用WebClient发出请求,并使用JSON.net进行反序列化。
目前,根据我的设置,每一个请求(包括将数据插入数据库)大约需要7秒,大约需要一个半小时才能完成。
接下来的问题变成了;是否可以使用async/await方法来加速这个过程?我读到的所有东西都是在UI方面的(即在处理请求时UI没有被冻结),但我想知道是否可以同时启动请求(或者,当时每10个请求启动一次)。为了完成这项工作,我添加了一个经过清理的代码版本(使它稍微短了一点,但没有删除任何逻辑)。
https://dotnetfiddle.net/S0fnBc

最佳答案

async/await用于异步操作。异步执行不等于并行执行。异步执行不会阻塞调用方,并行执行允许并发执行。你需要并行执行。为此,您可以使用Task Parallel Library。还有一本书是很好的读物。下面是一个简化的实现:

var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("/path/to/data");

var tasks = new Task<Task<HttpResponseMessage>>[5];

for (var i = 0; i < tasks.Length; i++)
{
    tasks[i] = Task<Task<HttpResponseMessage>>.Factory.StartNew(async () => await httpClient.GetAsync("?updatedFilterParams"));
}

Task.WhenAll(tasks); // wait for them to complete

foreach (var task in tasks)
{
    var data = task.Result.Result.Content.ReadAsStringAsync();
        // do something
}

需要注意的是:WebClient不支持并发请求,因此您要么为每个请求创建另一个请求,要么像我一样使用new。此外,在代码和数据之间有很多东西可以而且经常会对同一来源的并发请求施加限制,因此您需要限制一次触发的请求数量。

10-04 22:59
查看更多