webClient 机器人 - 多线程
我正在为在线游戏制作机器人。 它可以工作,但它是单线程应用程序。
我想让它成为多线程应用程序。 我知道后台工作者是如何工作的。
对于我的所有任务,我使用一个添加了 Cookie 支持的 WebClient。
例如,我需要打开一个页面,等待 10 分钟并执行下一条指令。 我还希望能够随时停止机器人。
我是否必须将 WebClient 对象传递给后台工作人员才能使用? 更新表单上的控件的最佳方法是什么?
我有一个类,它具有我想在主窗体上显示的所有值。 当属性发生变化时我应该触发一些事件吗?如果是的话,你能举个例子吗?
更新:
这是我的特殊 WebClient:
using System;
using System.Net;
namespace Game_Bot
{
class WebClientEx : WebClient
{
public CookieContainer CookieContainer { get; private set; }
public WebClientEx()
{
CookieContainer = new CookieContainer();
}
public void ClearCookies()
{
CookieContainer = new CookieContainer();
}
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = CookieContainer;
}
return request;
}
}
}
这是更新 UI 的好方法吗?或者还有更好的吗?
public void SetStatus(string status)
{
if (TransferLeftLabel.Dispatcher.Thread == Thread.CurrentThread)
{
TransferLeftLabel.Text = status;
}
else
{
TransferLeftLabel.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(Action)(() => { SetStatus(string status); }));
}
}
I'm making bot for online game.
It works, but it is singlethread application.
I want to make it multithread application.
I know how background worker works.
To all my tasks I use one WebClient with added Cookie support.
My for example needs to open one page, wait 10 min and do next instruction.
I also want to be able to stop bot at any time.
Do I have to pass my WebClient object to background worker to work with?
What is the best way to update controls on my Form?
I have one class that has all the values that I want to show on Main Form.
Should I fire some event when property changes? If yes, can you give me example?
UPDATE:
This is my Special WebClient:
using System;
using System.Net;
namespace Game_Bot
{
class WebClientEx : WebClient
{
public CookieContainer CookieContainer { get; private set; }
public WebClientEx()
{
CookieContainer = new CookieContainer();
}
public void ClearCookies()
{
CookieContainer = new CookieContainer();
}
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = CookieContainer;
}
return request;
}
}
}
Is this good way of updating UI? Or is there any beter?
public void SetStatus(string status)
{
if (TransferLeftLabel.Dispatcher.Thread == Thread.CurrentThread)
{
TransferLeftLabel.Text = status;
}
else
{
TransferLeftLabel.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(Action)(() => { SetStatus(string status); }));
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这就是我要做的:
首先:
在制作多线程应用程序(如您要修改的应用程序)时,我喜欢手动管理线程,而不是使用
BackgroundWorker
控件。要启动一个新线程,非常简单:
您可以获取任意数量的 Thread 实例,将它们存储在列表中,并按照您喜欢的方式进行管理。然而,线程并不是越多越好。在谷歌中搜索。
关于打开页面和保留 Cookie。
我认为您可以在表单中拥有一个类的实例,或者您拥有逻辑(线程可以访问的某个地方)(让我们将其命名为
WebUtils
),方法如下:GoToUrl()
或类似的内容,以及CookieCollection
作为该类中用于保存 cookie 的字段。您应该考虑的事情:
调用
GoToUrl
时,您可能需要执行 访问 cookies 变量时锁定,以避免不一致。关于更新控件:
您可以在
WebUtils
类中创建一个事件,每次访问页面时都可以触发该事件。在启动线程之前,您必须订阅Form
中的事件,在更新/访问/修改表单中的控件时,您可以使用 lock 执行类似的操作。现在,如何避免出现消息
Control ____accessed from a thread other than the thread it is created...
?下面是一个示例:
如果您想修改控件
textBox1
的属性Text
,而不是仅仅执行以下操作:textBox1.Text = "Ey,我访问了该站点< /code>
你可以这样做:
确保所有修改都是这样完成的。
这只是一个概述。
以下是关于一般线程的良好参考:C# 中的线程
编辑:
看一下线程的
IsBackground
属性。当您只想关闭应用程序时,这可能是应用程序冻结的原因。我建议创建一个类
WebUtils
,或者您想要的任何名称,因为这就是我过去创建它的方式。像这样的东西:
This is how I would do it:
First:
I like to manage threads manually instead of using the
BackgroundWorker
control when making multithreads applications like the one you want to modify.To start a new thread, it is as simple as:
You can get as many
Thread
instances as you want, store them in a list, and manage how you prefer. However, it isn't true that the more threads the better. Search in Google.About opening pages and keeping Cookies.
I think you could have an instance of a class in your Form, or where you have the logic (some place that threads can access), (let's name it
WebUtils
) with a method like:GoToUrl(<url here>)
or something like that, and aCookieCollection
as a field in that class to keep cookies.Something you should take in count:
When calling
GoToUrl
, you might need to do lock when accessing the cookies variable, to avoid inconsistency.About updating controls:
You can create an event inside the class
WebUtils
, and everytime the page is accessed you can fire this event. Before starting the threads, you must subscribe to the event in yourForm
, you can do something similar with lock when updating/accessing/modifying controls in your form.Now, how to avoid the message
Control ____ accessed from a thread other than the thread it was created...
?Here's an example:
If you want to modify property
Text
of the controltextBox1
, instead of just doing:textBox1.Text = "Ey, I accessed the site
you can do:
Make sure all the modifications are done like that.
This is just an overview. I'm not a thread expert.
Here is good reference about threadings in general: Threading in C#
Edit:
Take a look at the
IsBackground
property of threads. That could be the cause of application freezes when you just want to cose it.I suggested creating a class
WebUtils
, or however you want to name, because that's how I've created it in the past.Something like: