webClient 机器人 - 多线程

发布于 2024-11-03 00:07:05 字数 1525 浏览 4 评论 0原文

我正在为在线游戏制作机器人。 它可以工作,但它是单线程应用程序。

我想让它成为多线程应用程序。 我知道后台工作者是如何工作的。

对于我的所有任务,我使用一个添加了 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

千柳 2024-11-10 00:07:05

这就是我要做的:

首先:
在制作多线程应用程序(如您要修改的应用程序)时,我喜欢手动管理线程,而不是使用 BackgroundWorker 控件。

要启动一个新线程,非常简单:

public void SomeMethod() {
    var thread = new Thread(MyMethod);
    thread.Start(); //Will start the method
}

public void MyMethod() {
    //Do whatever you want inside the thread here
}

您可以获取任意数量的 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>

你可以这样做:

MethodInvoker m = () => { textBox1.Text = "Ey, I accessed the site" };
if (InvokeRequired)
    BeginInvoke(m);
else
    m.Invoke()

确保所有修改都是这样完成的。

这只是一个概述。
以下是关于一般线程的良好参考:C# 中的线程

编辑:
看一下线程的 IsBackground 属性。当您只想关闭应用程序时,这可能是应用程序冻结的原因。

我建议创建一个类 WebUtils,或者您想要的任何名称,因为这就是我过去创建它的方式。

像这样的东西:

public class WebUtils {
    CookieContainer _cookies;

    public WebUtils() {
        _cookies = new CookieContainer();
    }

    public void AccessPage(string url) {
        //Here I create a new instance of a HttpWebRequest class, and assign `_cookies` to its `Cookie` property.
        //Don't really know if `WebClient` has something similar
    }   
}

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:

public void SomeMethod() {
    var thread = new Thread(MyMethod);
    thread.Start(); //Will start the method
}

public void MyMethod() {
    //Do whatever you want inside the thread here
}

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 a CookieCollection 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 your Form, 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 control textBox1, instead of just doing:

textBox1.Text = "Ey, I accessed the site

you can do:

MethodInvoker m = () => { textBox1.Text = "Ey, I accessed the site" };
if (InvokeRequired)
    BeginInvoke(m);
else
    m.Invoke()

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:

public class WebUtils {
    CookieContainer _cookies;

    public WebUtils() {
        _cookies = new CookieContainer();
    }

    public void AccessPage(string url) {
        //Here I create a new instance of a HttpWebRequest class, and assign `_cookies` to its `Cookie` property.
        //Don't really know if `WebClient` has something similar
    }   
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文