- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个组件在单独的线程中处理多个 Web 请求。每个 WebRequest 处理都是同步的。
public class WebRequestProcessor:System.ComponentModel.Component
{
List<Worker> tlist = new List<Worker>();
public void Start()
{
foreach(string url in urlList){
// Create the thread object. This does not start the thread.
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
// Start the worker thread.
workerThread.Start(url);
tlist.Add(workerThread);
}
}
}
public class Worker
{
// This method will be called when the thread is started.
public void DoWork(string url)
{
// prepare the web page we will be asking for
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(url);
// execute the request
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
// we will read data via the response stream
Stream resStream = response.GetResponseStream();
// process stream
}
}
现在我必须找到取消所有请求的最佳方式。
一种方法是将每个同步WebRequest 转换为async 并使用WebRequest.Abort 取消处理。
另一种方法是释放线程指针并允许所有线程使用 GC 死亡。
最佳答案
如果要下载 1000 个文件,一次启动 1000 个线程当然不是最佳选择。与一次只下载几个文件相比,它不仅不会给您带来任何加速,而且还需要至少 1 GB 的虚拟内存。创建线程是昂贵的,尽量避免在循环中这样做。
您应该改为使用 Parallel.ForEach()
以及请求和响应操作的异步版本。例如像这样(WPF 代码):
private void Start_Click(object sender, RoutedEventArgs e)
{
m_tokenSource = new CancellationTokenSource();
var urls = …;
Task.Factory.StartNew(() => Start(urls, m_tokenSource.Token), m_tokenSource.Token);
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
m_tokenSource.Cancel();
}
void Start(IEnumerable<string> urlList, CancellationToken token)
{
Parallel.ForEach(urlList, new ParallelOptions { CancellationToken = token },
url => DownloadOne(url, token));
}
void DownloadOne(string url, CancellationToken token)
{
ReportStart(url);
try
{
var request = WebRequest.Create(url);
var asyncResult = request.BeginGetResponse(null, null);
WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle, token.WaitHandle });
if (token.IsCancellationRequested)
{
request.Abort();
return;
}
var response = request.EndGetResponse(asyncResult);
using (var stream = response.GetResponseStream())
{
byte[] bytes = new byte[4096];
while (true)
{
asyncResult = stream.BeginRead(bytes, 0, bytes.Length, null, null);
WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle,
token.WaitHandle });
if (token.IsCancellationRequested)
break;
var read = stream.EndRead(asyncResult);
if (read == 0)
break;
// do something with the downloaded bytes
}
}
response.Close();
}
finally
{
ReportFinish(url);
}
}
这样,当您取消操作时,所有下载都将被取消并且不会开始新的下载。此外,您可能想要设置 ParallelOptions
的 MaxDegreeOfParallelism
,这样您就不会一次下载太多。
我不确定您要对正在下载的文件做什么,因此使用 StreamReader
可能是更好的选择。
关于c# - 管理多个 WebRequest 的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6720113/
我正在查看 WebRequest.Create 之间的文档和 WebRequest.CreateHttp来决定我应该在我的应用程序中使用哪个。我没有看到这两种方法之间有什么不同,除了 WebReque
我想知道 DefaultWebProxy 和 GetSystemWebProxy() 之间的主要区别是什么。 MSDN 上有一些描述,但我仍然觉得我需要更多细节才能更好地理解。 此外,假设我在 C#
我想在 UI 上显示下载正在进行时下载文件。使用 WebRequest 我有两个选择: 使用 WebRequest.BeginGetResponse 和相关方法。 优点:可以以字节为单位显示准确的进度
我正在尝试注销对 MonoTouch 库的引用,所使用的是: IWebProxy oDefaultProxy = CFNetwork.GetDefaultProxy (); 在 .NET 中,还有
我首先发布了这个:HttpWebRequest: How to find a postal code at Canada Post through a WebRequest with x-www-fo
在 Windows PowerShell 3.0 中引入了 Invoke-RestMethod小命令。 Invoke-RestMethod cmdlet 接受 -Body用于设置请求正文的参数。 由于
我正在尝试在.bat文件中下载一个exe,但是无法隐藏输出 $progressPreference = 'silentlyContinue'| Out-Null 和$null 2>&1. 我不知道为什
我正在尝试 curl 包含分号的有效负载,但它失败了 Invoke-WebRequest -Uri $uri -Body '{"text" : "foo;"}' -Method Post Invoke
我有一个带有状态页面的网络设备,该页面可以通过Java小程序访问。使用Fiddler,我可以找到状态的http提要,但是页面会不断刷新。 (Firefox会显示该页面,但会保持刷新状态,Chrome会
有人可以向我解释为什么cUrl(真正的网址)有效但Invoke-WebRequest无效吗?同一台机器,相同变量。在我看来,他们俩都应该做同样的事情,将文件上传到jfrog Artifactory。
我正在尝试在 WebRequest 中发送表单数据。 该函数工作正常并按预期返回“成功”响应流。 但是,如果“data”变量的长度超过 30,000 个字符,我会遇到 HTTP 500 错误: Mes
我正在尝试在 WebRequest 中发送表单数据。 该函数工作正常并按预期返回“成功”响应流。 但是,如果“data”变量的长度超过 30,000 个字符,我会遇到 HTTP 500 错误: Mes
下面的代码需要怎么修改才能发送WebRequest通过指定的 proxy server和 port number ? Dim Request As HttpWebRequest = WebReques
我想执行一堆 WebRequest,但设置了可以同时启动的阈值。 我遇到了这个LimitedConcurrencyTaskScheduler example并尝试像这样使用它 scheduler =
我使用下面的代码在线检查一些pdf文件并相应地返回一个字符串。 问题是:当我添加第二个 Task.Factory.StartNew() 时,它开始复制所有请求,但仍然只返回一个答案(应该如此)。 我需
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseurl + url); req.Timeout = 1000 * 10;
我正在使用 WebRequest 执行简单请求,应用程序只是挂起,直到响应返回。我该如何解决这个问题? 看了很多题目,都说要用线程。我不知道如何使用它们;任何人都可以提供以下不挂起用户界面的示例吗?
以下代码在 WinForms 和 Windows Phone 8 应用程序中返回错误。 代码 var jsonData = "jsonStringGoesHere"; var uri
我正在用 C# 构建一个网络抓取工具,用于处理代理和大量请求。页面通过 ConnectionManager 类加载,该类获取代理并使用随机代理重试加载该页面,直到页面被正确加载。 平均一个任务需要10
我在做一个项目,多次调用一个网址 request = (HttpWebRequest)WebRequest.Create(url); request.GetResponse(); 这是我的代码。
我是一名优秀的程序员,十分优秀!