C# ASP.NET多线程Web请求
我正在ASP.NET解决方案中构建一个页面,该页面从第三方API服务检索其大部分数据 页面本身需要对API进行大约5次不同的调用,以填充其所有控件,因为对API的每个Web请求都会返回不同的数据集 我想在一个新线程上同时处理每个单独的Web请求,以减少加载时间 我提出的每个请求如下所示:-C# ASP.NET多线程Web请求,c#,asp.net,multithreading,webrequest,C#,Asp.net,Multithreading,Webrequest,我正在ASP.NET解决方案中构建一个页面,该页面从第三方API服务检索其大部分数据 页面本身需要对API进行大约5次不同的调用,以填充其所有控件,因为对API的每个Web请求都会返回不同的数据集 我想在一个新线程上同时处理每个单独的Web请求,以减少加载时间 我提出的每个请求如下所示:- WebRequest request = WebRequest.Create(requestUrl); string response = new StreamReader(request.GetRespo
WebRequest request = WebRequest.Create(requestUrl);
string response = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
return new JsonSerializer().Deserialize<OccupationSearch>(new JsonTextReader(new StringReader(response)));
WebRequest-request=WebRequest.Create(requestUrl);
字符串响应=新的StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
返回新的JsonSerializer()。反序列化(新的JSONtexReader(新的StringReader(响应));
首先,我应该尝试一下吗?i、 e,安全吗?它将通过多线程来提高性能
第二,做这件事的最佳方式是什么?多线程系统有许多不同的方式,但哪种方式最适合此任务?我认为多线程(合理)将提供好处,因为您的代码编写方式知道对GetResponse()的调用。GetResponseStream()被阻塞 提高性能的最简单方法之一是使用:
var url=newlist();
var结果=新的ConcurrentBag();
Parallel.ForEach(url,url=>
{
WebRequest=WebRequest.Create(requestUrl);
字符串响应=新的StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
var result=JsonSerializer()。反序列化(新的JsonTextReader(新的StringReader(响应));
结果。添加(结果);
});
如果您使用的是.NET4.5,那么新的方法是使用async/await。Msdn在这里有一篇关于这个主题的非常广泛的文章:和
Scott Hanselman在这个主题上也有一篇很好看的博文:多线程是正确的选择,但我称之为异步执行 无论如何,您应该知道多线程在IIS中的工作方式不同 一旦所有子线程结束,IIS工作进程将完成一个请求,这是一个大问题,因为您不希望长时间保留一个工作进程,而是将其重新用于其他请求。实际上这是一个线程池 这就是为什么ASP.NET提供了自己的实现异步的方法,如果使用正确的方法,IIS将能够一次处理更多请求,因为异步工作将在IIS进程模型之外执行 我建议您阅读有关ASP.NET async的更多信息:
HttpClient
与以下组件一起使用:
每个web请求都应该是IIS中不同的工作线程,具体取决于您的服务负载以及IIS的设置方式。因此,如果您谈论多线程,您将尝试将每个请求完成的工作细分为多个线程。我将研究异步执行。使用
request.GetResponseAsync()
等。由于List
不是线程安全的(用于写入),您不需要lock(results)
吗?公平地说,老实说,我不确定列表是否会丢失任何东西,因为它没有读取和写入。但为了安全起见,我将更新以使用ConcurrentBag。列表正在写入-它正在写入结果的添加
。你只需要在它周围加一个锁就行了。谢谢你的建议。@Derek,没问题。事实上,你应该走这条路,因为其他方法会以死锁告终。谢谢你的建议
var urls = new List<string>();
var results = new ConcurrentBag<OccupationSearch>();
Parallel.ForEach(urls, url =>
{
WebRequest request = WebRequest.Create(requestUrl);
string response = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
var result = JsonSerializer().Deserialize<OccupationSearch>(new JsonTextReader(new StringReader(response)));
results.Add(result);
});
public async Task<OccupationSearch> GetOccupationAsync(string requestUrl)
{
// You can also reuse HttpClient instances instead of creating a new one each time
using (var client = new HttpClient())
{
var response = client.GetStringAsync(requestUrl);
return new JsonSerializer().Deserialize<OccupationSearch>(new JsonTextReader(new StringReader(response)));
}
}
List<string> urls = ...;
OccupationSearch[] results = await Task.WhenAll(urls.Select(GetOccupationAsync));