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)
{
开发者_JAVA百科 if (TransferLeftLabel.Dispatcher.Thread == Thread.CurrentThread)
{
TransferLeftLabel.Text = status;
}
else
{
TransferLeftLabel.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(Action)(() => { SetStatus(string status); }));
}
}
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
}
}
精彩评论