在 Main 中处理线程化 Web 请求?
我正在用 C# 编写一个应用程序,并且正在创建多个BackgroundWorker 线程来从网页中获取信息。尽管它们是后台工作人员,但我的 GUI 表单变得没有响应。
当我调试时,当程序无响应时我会暂停,我可以看到我在主线程中,并且暂停在网页获取方法上。不过,此方法仅从新线程调用,因此我无法弄清楚为什么我会出现在主线程中。
这有什么意义吗?我可以做什么来确保 Web 请求仅在各自的线程中处理?
编辑:一些代码和解释
我正在处理大量地址。每个线程将处理一个或多个地址。我可以选择要创建多少个线程(我保持谦虚:))
//in “Controller” class
public void process()
{
for (int i = 1; i <= addressList.Count && i<= numthreads; i++)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += doWork;
bw.RunWorkerAsync((object)i);
}
}
public void doWork(object sender, DoWorkEventArgs e)
{
//create an object that has the web fetching method, call it WorkObject
//WorkObject keeps a reference to Controller.
//When it is done getting information, it will send it to Controller to print
//generate a smaller list of addresses to work on, using e.Argument (should be 'i' from the above 'for' loop)
WorkObject.workingMethod()
}
当创建 WorkObject 时,它使用“i”来知道它是什么线程号。它将使用它来获取要从中获取信息的网址列表(从主表单、控制器和每个工作对象共享的较大地址列表中 - 每个线程将处理较小的地址列表)。当它迭代列表时,它将调用“getWebInfo”方法。
//in “WorkObject” class
public static WebRequest request;
public void workingMethod()
{
//iterate over the small list of addresses. For each one,
getWebInfo(address)
//process the info a bit...then
myController.print()
//note that this isn’t a simple “for” loop, it involves event handlers and threading
//Timers to make sure one is done before going on to the next
}
public string getWebInfo (string address)
{
request = WebRequest.Create(address);
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string content = reader.ReadToEnd();
return content;
}
I'm writing an application in C#, and I am creating multiple BackgroundWorker threads to grab information from webpages. Despite them being BackgroundWorkers, my GUI Form is becoming unresponsive.
When I am debugging, I pause when the program goes unresponsive, and I can see that I am in the Main Thread, and I am paused on the webpage fetching method. This method is only called from new threads, though, so I can’t figure out why I would be there in the Main Thread.
Does this make any sense? What can I do to make sure the web requests are only being handled in their respective threads?
EDIT: some code and explanation
I am processing a large list of addresses. Each thread will be processing one or more addresses. I can choose how many threads I want to create (I keep it modest :))
//in “Controller” class
public void process()
{
for (int i = 1; i <= addressList.Count && i<= numthreads; i++)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += doWork;
bw.RunWorkerAsync((object)i);
}
}
public void doWork(object sender, DoWorkEventArgs e)
{
//create an object that has the web fetching method, call it WorkObject
//WorkObject keeps a reference to Controller.
//When it is done getting information, it will send it to Controller to print
//generate a smaller list of addresses to work on, using e.Argument (should be 'i' from the above 'for' loop)
WorkObject.workingMethod()
}
When WorkObject is created, it uses “i” to know what thread number it is. It will use this to get a list of web addresses to get information from (from a larger list of addresses which is shared by the main Form, the Controller, and each of the WorkObjects – each thread will process a smaller list of addresses). As it iterates over the list, it will call the “getWebInfo” method.
//in “WorkObject” class
public static WebRequest request;
public void workingMethod()
{
//iterate over the small list of addresses. For each one,
getWebInfo(address)
//process the info a bit...then
myController.print()
//note that this isn’t a simple “for” loop, it involves event handlers and threading
//Timers to make sure one is done before going on to the next
}
public string getWebInfo (string address)
{
request = WebRequest.Create(address);
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string content = reader.ReadToEnd();
return content;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该在您的BackgroundWorker 的DoWork 事件中执行所有网络工作,是吗?
一些剪辑的代码可能会帮助我们理解发生了什么。
You should be performing all the web-work in your BackgroundWorker's DoWork event, are you?
Some clipped code may help us to understand what's going on.
在类似的情况下,我发现通过创建自己的线程(没有BackgroundWorker和ThreadPool)并限制活动连接的数量,我可以更好地控制。将 IP 地址写入队列,然后选取每个地址,将其传递给帮助程序类,在该类中您可以在新线程上调用其 DoSomething 方法。通过在启动线程时递增计数器并在线程完成时递减计数器来进行限制。您可以使用帮助程序类中的回调例程来向 UI 线程发出信号以更新界面或指示线程已完成。
使用 UI 改变油门限制并观察任务管理器以查看对内存和 CPU 使用率的影响。您可以在 app.config 中添加 maxconnection 设置以获得更多并发连接。
In a similar situation I found I had better control by creating my own threads (no BackgroundWorker and no ThreadPool) and throttling the number of active connections. Write the IP addresses to a Queue and then pick each one off, passing it to a helper class where you call its DoSomething method on a new thread. Throttle by incrementing a counter when you launch a thread and decrement it when the thread completes. You can use callback routines from your helper class to signal your UI thread to update the interface or indicate a thread is finished.
Use your UI to vary the throttle limit and watch the Task Manager to see the effect on memory and CPU usage. You can add a maxconnection setting in your app.config to get more simultaneous connections.
我无法弄清楚为什么后台工作人员导致挂起,但我没有使用同步 HTTP 请求,而是使用本指南切换到异步:
http://www.developerfusion.com/code/4654/asynchronous-httpwebrequest/
清除了所有挂起的内容。感谢您的回复。
I couldn't figure out why the background workers were causing hanging, but instead of using synchronous HTTP requests I switched to asynchronous using this guide:
http://www.developerfusion.com/code/4654/asynchronous-httpwebrequest/
Cleared up all the hanging. Thanks for the responses.