【问题标题】:webClient Bot - MultithreadingwebClient Bot - 多线程
【发布时间】:2011-04-22 08:44:00
【问题描述】:

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

我想让它成为多线程应用程序。 我知道后台工作人员的工作原理。

对于我的所有任务,我使用一个添加了 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); }));
        }
    }

【问题讨论】:

  • 如果你想让多个线程工作,我建议你手动使用线程而不是BackgroundWorker控件。
  • 使用手动线程,您还可以发送您想要的任何状态更新(通过在主线程上调用委托并检查 InvokeRequired)。 Backgroundworker 仅支持向 UI 报告百分比。

标签: c# .net backgroundworker webclient bots


【解决方案1】:

我会这样做:

第一: 在制作多线程应用程序时,我喜欢手动管理线程,而不是使用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 实例,将它们存储在列表中,并按照您的喜好进行管理。但是,并不是说线程越多越好。在 Google 中搜索。

关于打开页面和保存 Cookie。

我认为你可以在你的表单中有一个类的实例,或者你有逻辑的地方(线程可以访问的某个地方),(让我们将其命名为WebUtils),方法如下:GoToUrl(<url here>) 或其他东西像这样,并将 CookieCollection 作为该类中的字段来保存 cookie。

你应该考虑的东西:

调用GoToUrl时,访问cookies变量时可能需要lock,以避免不一致。

关于更新控件:

您可以在WebUtils 类中创建一个事件,并且每次访问该页面时都可以触发该事件。在开始线程之前,您必须在 Form 中订阅事件,您可以在更新/访问/修改表单中的控件时使用 lock 执行类似的操作。

现在,如何避免消息Control ____ accessed from a thread other than the thread it was created...

这是一个例子:

如果你想修改控件textBox1的属性Text,而不是仅仅这样做:

textBox1.Text = "Ey, I accessed the site

你可以这样做:

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

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

这只是一个概述。我不是线程专家。
以下是关于线程的参考:Threading in 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
    }   
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 2022-09-27
    相关资源
    最近更新 更多