I am trying to code a multithreaded WebBrowser application.
The WebBrowser elements will just navigate to a given URL,
wait until it loads and then
click a button or
submit the form.
This should happen in a loop forever.
I'm using Microsoft Visual Studio 2010 and Windows Forms
Here's my code:
//added windows form 30 webbrowser object
//and now assigning them to an webbrowser array
wbList[0] = webBrowser1; wbList[1] = webBrowser2; wbList[2] = webBrowser3;
wbList[3] = webBrowser4; wbList[4] = webBrowser5; wbList[5] = webBrowser6;
wbList[6] = webBrowser7; wbList[7] = webBrowser8; wbList[8] = webBrowser9;
//etc. until:
wbList[29] = webBrowser30;
for (int i = 0; i < 30; i++)
{
wbList[i].ScriptErrorsSuppressed = true;
wbList[i].NewWindow += new CancelEventHandler(wb_NewWindow);
}
//********************************** creating threads here
Thread[] AllThread = new Thread[100];
int irWhichWbb = 0;
for (int nn = irDirectPostCount; nn < irNumber+1; nn++)
{
AllThread[nn] = new Thread(new
ParameterizedThreadStart(this.MultiThreadWebBrowser));
AllThread[nn].Start(nn.ToString() + ";" + irWhichWbb.ToString());
irWhichWbb++;
}
Application.DoEvents();
for (int nn = 0; nn < irNumber+1; nn++)
{ AllThread[nn].Join(); }
//Multi thread function
void MultiThreadWebBrowser(object parameter)
{
string srParam = parameter.ToString();
int i = Convert.ToInt32 (srParam.Substring(0,(srParam.IndexOf(";"))));
int irWhichWb = Convert.ToInt32(srParam.Substring(srParam.IndexOf(";")+1));
string hdrs = "Referer: http://www.xxxxxxxxx.com/xxxxxxxxxx.aspx";
try
{
wbList[irWhichWb].Navigate(srVotingList[i, 0], "_self", null, hdrs);
}
catch { }
try { waitTillLoad(irWhichWb); }
catch { }
waitTillLoad3();
}
// wait until webbrowser navigate url loaded
private void waitTillLoad(int irWhichLoad)
{
WebBrowserReadyState loadStatus;
//wait till beginning of loading next page
int waittime = 100000;
int counter = 0;
while (true)
{
try
{
loadStatus = wbList[irWhichLoad].ReadyState;
Application.DoEvents();
if ((counter > waittime) ||
(loadStatus == WebBrowserReadyState.Uninitialized) ||
(loadStatus == WebBrowserReadyState.Loading) ||
(loadStatus == WebBrowserReadyState.Interactive))
{
break;
}
counter++;
}
catch { }
}
//wait till the page get loaded.
counter = 0;
while (true)
{
try
{
loadStatus = wbList[irWhichLoad].ReadyState;
Application.DoEvents();
if (loadStatus == WebBrowserReadyState.Complete)
{
break;
}
if (counter > 10000000)
break;
counter++;
}
catch { }
}
}
private void waitTillLoad3()
{
DateTime dtStart = DateTime.Now;
while (true)
{
if ((DateTime.Now - dtStart).TotalMilliseconds > 4000)
break;
Application.DoEvents();
}
}
You don't say what kind of failure you get: "doesn't work" is not a good description.
I would first try with just a single thread. Does that work?
You have empty catch blocks, so you are silently ignoring some error conditions. This may well by hiding a problem.
Related
I have the following problem and hope someone can help me.
My basic flow: I want to program any number of devices in parallel using the FTDI D2XX driver and then communicate with them for testing purposes. For this I use two arrays from BackgroundWorker - the first array for programming and the second for testing.
Programming works without any problems. But if I start the BackgroundWorker from the second array to start the test, the connection fails. If I run the complete sequence with only one BackgroundWorker for programming and one BackgroundWorker for testing, the sequence works without problems.
Initialization of BackgroundWorker
private void InitializeBackgoundWorkers()
{
for (var f = 0; f < ftdiDeviceCount; f++)
{
threadArrayProgram[f] = new BackgroundWorker();
threadArrayProgram[f].DoWork += new DoWorkEventHandler(bgr_WorkerStirrerProg_DoWork);
threadArrayProgram[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerProgRunWorkerCompleted);
threadArrayProgram[f].WorkerReportsProgress = true;
threadArrayProgram[f].WorkerSupportsCancellation = true;
}
for (var f = 0; f < ftdiDeviceCount; f++)
{
threadArrayTest[f] = new BackgroundWorker();
threadArrayTest[f].DoWork += new DoWorkEventHandler(bgr_WorkerStirrerTest_DoWork);
threadArrayTest[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerTestRunWorkerCompleted);
threadArrayTest[f].WorkerReportsProgress = true;
threadArrayTest[f].WorkerSupportsCancellation = true;
}
}
Aufruf der BackgroundWorker
private void button2_Click_1(object sender, EventArgs e)
{
if (!bStirrerSerached)
{
vSetProgressBarValueRuehrer(1, imaxprogressbar);
vSearchStirrer();
}
if (FtStatus == FTDI.FT_STATUS.FT_OK)
{
//bgr_Worker_Stirrer.RunWorkerAsync();
InitializeBackgoundWorkers();
//---programmieren---//
for (var f = 0; f < /*FilesToProcess*/ftdiDeviceCount; f++)
{
var fileProcessed = false;
while (!fileProcessed)
{
for (var threadNum = 0; threadNum < MaxThreads; threadNum++)
{
if (!threadArrayProgram[threadNum].IsBusy)
{
Console.WriteLine("Starting Thread: {0}", threadNum);
stemp = "Starting Thread: " + threadNum;
File.AppendAllText(slogfile, stemp);
threadArrayProgram[threadNum].RunWorkerAsync(f);
fileProcessed = true;
Thread.Sleep(1000);
break;
}
}
if (!fileProcessed)
{
Thread.Sleep(50);
}
}
}
//---testen---//
for (var f = 0; f < /*FilesToProcess*/ftdiDeviceCount; f++)
{
var fileProcessed = false;
while (!fileProcessed)
{
for (var threadNum = 0; threadNum < MaxThreads; threadNum++)
{
if (!threadArrayTest[threadNum].IsBusy)
{
Console.WriteLine("Starting Thread: {0}", threadNum);
stemp = "Starting Thread: " + threadNum;
File.AppendAllText(slogfile, stemp);
threadArrayTest[threadNum].RunWorkerAsync(f);
fileProcessed = true;
Thread.Sleep(1000);
break;
}
}
if (!fileProcessed)
{
Thread.Sleep(50);
}
}
}
}
button2.Enabled = false;
}
BackgroundWorker
private void bgr_WorkerStirrerProg_DoWork(object sender, DoWorkEventArgs e)
{
try
{
if (FtStatus == FTDI.FT_STATUS.FT_OK)
{
if (ftdiDeviceList != null)
{
//---db werte sammeln---//
cRuehrerProp = new CRuehrerProperties();
cRuehrerProp.SBenutzer = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
cRuehrerProp.SComputername = System.Windows.Forms.SystemInformation.ComputerName.ToString();
//---Rührer programmieren---//
vStirrerProgram((int)e.Argument);
}
}
}
catch (NotSupportedException /*exc*/)
{
}
finally
{
this.Invoke((MethodInvoker)delegate
{
});
}
}
private void bgr_WorkerStirrerTest_DoWork(object sender, DoWorkEventArgs e)
{
try
{
if (!bfinish)
{
while (!bfinish)
{
if (bfinish)
break;
}
}
//---Test starten---//
vStirrerTest((int)e.Argument);
}
catch (NotSupportedException /*exc*/)
{
}
finally
{
this.Invoke((MethodInvoker)delegate
{
button2.Enabled = true;
myFtdiDevice.Close();
});
}
}
Testing method
private void vStirrerTest(int pos)
{
//threadnr
iPosRuehrerGrid = pos;
Console.WriteLine("Thread {0} StirrerTest", pos);
ftStatus = myFtdiDevice.CyclePort();
UInt32 newFtdiDeviceCount = 0;
do
{
// Wait for device to be re-enumerated
// The device will have the same location since it has not been
// physically unplugged, so we will keep trying to open it until it succeeds
ftStatus = myFtdiDevice.OpenByLocation(ftdiDeviceList[iPosRuehrerGrid].LocId);
Console.WriteLine("try to open locid" + ftdiDeviceList[iPosRuehrerGrid].LocId + " on device " + iPosRuehrerGrid);
//ftStatus = myFtdiDevice.OpenByLocation(ftdiDeviceListOrig[iStirrerPosold[iPosRuehrerGrid]].LocId);
Thread.Sleep(1000);
} while (ftStatus != FTDI.FT_STATUS.FT_OK);
// Close the device
myFtdiDevice.Close();
// Re-create our device list
ftStatus = myFtdiDevice.GetNumberOfDevices(ref newFtdiDeviceCount);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
{
// Wait for a key press
Console.WriteLine("Failed to get number of devices (error " + ftStatus.ToString() + ")");
stemp = "Failed to get number of devices (error " + ftStatus.ToString() + ")";
File.AppendAllText(slogfile, stemp);
return;
}
// Re-populate our device list
ftStatus = myFtdiDevice.GetDeviceList(ftdiDeviceList);
bRepopulateList = true;
vSearchStirrer();
The error occurs in the do loop. If I use only one device - and thus only one thread at a time, it takes an average of 5 runs until the device is opened again. However, if I attach another device and thus have 2 programming and 2 test threads, it does not manage to open the desired device.
I have looked at the DeviceList to make sure it is looking for the right device with the right ID - which it is.
Since I don't have any experience with the Backgrounworker yet, I'm not sure if I haven't forgotten something, which is why this error occurs.
I need to compress more folder at same time in different archivie to goes more quikly.
I tried to use a main backgroundworker and from this I did a for cycle to start other backgroundworker for each folder. I notice that the backgroundworker starts all at same time but not works together what is the best way to do a parallel archive?what you suggest?
to create the archive I use the zipforge library
DoWork of the main backgroundworker
if (Directory.Exists(destination))
{
if (MessageBox.Show("", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
{
goto EXIT_UTENTE;
}
else
{
bool finish = false;
int j = 1;
string dest_appoggio = destination;
do
{
dest_appoggio = destination + "_" + j;
if (Directory.Exists(dest_appoggio))
{
j++;
}
else
{
destination = dest_appoggio;
dataprogressiva = data + "_" + j;
finish = true;
}
}
while (finish == false);
}
}
destinationdefault = destination;
var row_list1 = GetDataGridRows(dgwRobot);
int riga = -1;
foreach (DataGridRow single_row1 in row_list1)
{
bool rowselected = false;
single_row1.Dispatcher.Invoke(new Action(() => { rowselected = single_row1.IsSelected; }));
if (rowselected == true)
{
riga = single_row1.GetIndex();
var robotProcessed = false;
while (!robotProcessed)
{
for (var threadNum = 0; threadNum < MaxBackupContemporanei; threadNum++)
{
if (!threadArray[threadNum].IsBusy)
{
threadArray[threadNum].RunWorkerAsync(riga);
robotProcessed = true;
break;
}
}
}
}
Thread.Sleep(500);
}
bool bwTerminati = false;
while (!bwTerminati)
{
for (var threadNum = 0; threadNum < MaxBackupContemporanei; threadNum++)
{
if (threadArray[threadNum].IsBusy)
{
bwTerminati = false;
threadNum = MaxBackupContemporanei;
}
else
{
bwTerminati = true;
}
}
}
A script on this page is causing your web browser to run slowly
I am trying to get content of multiple web pages in a loop, after browsing ~ 38 URLs the code become irresponsible, below is the code. The intent of this activity. I have looked for multiple option on web nothing helped.
This code section getting the page content of URL passed as parameter
public HtmlAgilityPack.HtmlDocument GetPageSource(string url)
{
webBrowserCtrl = new WebBrowser();
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
StringReader content = null;
webBrowserCtrl.ScriptErrorsSuppressed = true;
webBrowserCtrl.Navigate(url);
waitTillLoad(webBrowserCtrl);
IHTMLDocument3 documentAsIHtmlDocument = null;
try
{
documentAsIHtmlDocument = (mshtml.IHTMLDocument3)webBrowserCtrl.Document.DomDocument;
content = new StringReader(documentAsIHtmlDocument.documentElement.outerHTML);
doc.Load(content);
}
catch
{
Console.Write("Exception from web Page: {0}", url);
}
finally
{
if (documentAsIHtmlDocument != null)
{
Marshal.ReleaseComObject(documentAsIHtmlDocument);
documentAsIHtmlDocument = null;
}
content.Dispose();
content.Close();
webBrowserCtrl.Dispose();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
EmptyWorkingSet(Process.GetCurrentProcess().Handle);
}
return doc;
}
private void waitTillLoad(WebBrowser webBrControl)
{
while (webBrControl.IsBusy)
Application.DoEvents();
for (int i = 0; i < 500; i++)
{
if (webBrControl.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
{
Application.DoEvents();
Thread.Sleep(10);
}
else
break;
}
WebBrowserReadyState loadStatus;
int waittime = 100000;
//System.Threading.Thread.Sleep(1000000);
int counter = 0;
while (true)
{
loadStatus = webBrControl.ReadyState;
Application.DoEvents();
if ((counter > waittime) || (loadStatus == WebBrowserReadyState.Uninitialized) || (loadStatus == WebBrowserReadyState.Loading) || (loadStatus == WebBrowserReadyState.Interactive))
{
break;
}
counter++;
}
counter = 0;
while (true)
{
loadStatus = webBrControl.ReadyState;
Application.DoEvents();
if (loadStatus == WebBrowserReadyState.Complete && webBrControl.IsBusy != true)
{
break;
}
counter++;
}
}
Your problem is your waitTillLoad function. You should not do ANY processing of the HTML document of any kind, until AFTER you leave the method where your tell your web browser to navigate. Its a threading thing since your web browser and your GUI are on the same thread you need to use the events to get stuff done.
So you should first hook into the DocumentCompleted Event, and then call your waitTillLoad like so:
public HtmlAgilityPack.HtmlDocument GetPageSource(string url)
{
webBrowserCtrl = new WebBrowser();
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
StringReader content = null;
webBrowserCtrl.ScriptErrorsSuppressed = true;
webBrowserCtrl.Navigate(url);
webBrowserCtrl.DocumentCompleted += webBrowserCtrl_DocumentCompleted;
}
private void webBrowserCtrl_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
waitTillLoad(webBrowserCtrl);
IHTMLDocument3 documentAsIHtmlDocument = null;
try
{
documentAsIHtmlDocument = (mshtml.IHTMLDocument3)webBrowserCtrl.Document.DomDocument;
content = new StringReader(documentAsIHtmlDocument.documentElement.outerHTML);
doc.Load(content);
}
catch
{
Console.Write("Exception from web Page: {0}", url);
}
finally
{
if (documentAsIHtmlDocument != null)
{
Marshal.ReleaseComObject(documentAsIHtmlDocument);
documentAsIHtmlDocument = null;
}
content.Dispose();
content.Close();
webBrowserCtrl.Dispose();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
EmptyWorkingSet(Process.GetCurrentProcess().Handle);
}
return doc;
}
private void waitTillLoad(WebBrowser webBrControl)
{
while (webBrControl.IsBusy)
Application.DoEvents();
for (int i = 0; i < 500; i++)
{
if (webBrControl.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
{
Application.DoEvents();
Thread.Sleep(10);
}
else
break;
}
WebBrowserReadyState loadStatus;
int waittime = 100000;
//System.Threading.Thread.Sleep(1000000);
int counter = 0;
while (true)
{
loadStatus = webBrControl.ReadyState;
Application.DoEvents();
if ((counter > waittime) || (loadStatus == WebBrowserReadyState.Uninitialized) || (loadStatus == WebBrowserReadyState.Loading) || (loadStatus == WebBrowserReadyState.Interactive))
{
break;
}
counter++;
}
counter = 0;
while (true)
{
loadStatus = webBrControl.ReadyState;
Application.DoEvents();
if (loadStatus == WebBrowserReadyState.Complete && webBrControl.IsBusy != true)
{
break;
}
counter++;
}
}
}
Hi guys I have such construction:
Start threads:
Thread[] thr;
int good_auth, bad_auth, good_like, bad_like;
static object accslocker = new object();
static object limitlocker = new object();
string acc_path, proxy_path, posts_path;
int position_of_limit, position = 0;
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
decimal value = numericUpDown1.Value;
int i = 0;
int j = (int)(value);
thr = new Thread[j];
for (; i < j; i++)
{
thr[i] = new Thread(new ThreadStart(go));
thr[i].IsBackground = true;
thr[i].Start();
}
}
And than function go:
public void go()
{
while (true)
{
string acc = "";
string proxy = "";
lock (limitlocker)
{
if (position_of_limit >= int.Parse(textBox2.Text) - 1)
{
position_of_limit = 0;
if (position < posts.Count - 1)
position++;
else
{
break;
}
}
}
lock (accslocker)
{
if (accs.Count == 0)
{
break;
}
else
acc = accs.Dequeue();
}
OD od = new OD(acc);
string login = od.Auth();
if (login == "Login")
{
lock (accslocker)
{
good_auth++;
log_good_auth(good_auth);
}
string like = od.like(posts[position], textBox1.Text);
if (like == "Good")
{
lock (accslocker)
{
position_of_limit++;
good_like++;
log_good_like(good_like);
}
}
else if (like == "Failed")
{
lock (accslocker)
{
bad_like++;
log_bad_like(bad_like);
}
}
else
{
lock (accslocker)
{
bad_like++;
log_bad_like(bad_like);
}
}
}
else if (login == "Spamblock")
{
lock (accslocker)
{
bad_auth++;
log_bad_auth(bad_auth);
}
}
else if (login == "Locked")
{
lock (accslocker)
{
bad_auth++;
log_bad_auth(bad_auth);
}
}
else if (login == "Invalid")
{
lock (accslocker)
{
bad_auth++;
log_bad_auth(bad_auth);
}
}
else if (login == "Bad_proxy")
{
lock (accslocker)
{
accs.Enqueue(acc);
Proxy.proxies.Remove(proxy);
}
}
else
{
lock (accslocker)
{
accs.Enqueue(acc);
Proxy.proxies.Remove(proxy);
}
}
}
}
I start for example 20 threads, when position_of_limit becomes bigger than int.Parse(textBox2.Text) - 1 all threads need to take next posts[position] in next loop. But I receive an exception on line string like = od.like(posts[position], textBox1.Text);
"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
How to solve this problem? Thanks
Locking the GUI thread is evil, since it's an STA thread.
That means it must manage a message loop and is not allowed to block. So blocking is likely to cause deadlocks.
Rather use callbacks like BackgroundWorker.RunWorkerCompleted.
Some other informative links about locking:
Guidelines of when to use locking
Obtaining lock on a UI thread
I a have microchip mcp2200 device. To device is attached tree buttons (as digital inputs).
I use it as feedback machine.
I attached it to windows server 2003 x64. Then i used microchips mcp2200 driver and Managed SimpleIO DLL in my C# app.
In C# i use time with frequency 500 ms to check if button was pressed. After hour or two server has constant high cpu usage. If i kill C# program, all is ok. How can i lover cpu usage? Or my code has wrong?
Some code:
void timer1_Tick(object sender, EventArgs e)
{
if (DateTime.Now.ToString("HH") == _turnOffApp) Environment.Exit(0); //after working hours, turn off app. Task scheduler will start it at 8 AM
if (btn_down == 99)
{ //if button is UP
bool connStatus = SimpleIOClass.IsConnected();
if (connStatus)
{
lblConnStatus.Text = "Connected";
unsafe
{
uint rez1 = 2;
uint* rez = &rez1;
for (uint i = 0; i < 8; i++)
{
if (i == 5 || i == 7) continue; //unused pins
rez1 = 2;
if (SimpleIOClass.ReadPin(i, rez))
{
string rez11 = rez1.ToString();
this.Controls["label" + i.ToString()].Text = rez1.ToString();
if (rez1.ToString() == "0") // 0 = button down, 1 = button up
{
RegisterButton(i);
i = 8;
continue;
}
}
else
{
try { this.Controls["label" + i.ToString()].Text = "ReadPinErr"; }
catch { }
}
}
}
}
else
{
lblConnStatus.Text = "NOT Connected";
}
}//end btn_down == 99
}
void RegisterButton(uint poga)
{
btn_down = poga;
device = Device(poga);
CheckUserInput();
}
void SendBtnToServer(string btn)
{
try
{
string uri = #"http://web-server.lan/pogas.php?device="+ device+ "&p=" + btn;
WebClient clietn = new WebClient();
clietn.Headers.Add("Cache-Control", "no-cache");
clietn.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
clietn.DownloadString(uri);
clietn.Dispose();
}
catch (Exception ex) { try { File.AppendAllText(logFails, DateTime.Now.ToString() + " " + ex.ToString() + "\n\r"); } catch { } }
}
void CheckUserInput()
{
Thread.Sleep(2000); //wait 2 sec until user releases button
bool connStatus = SimpleIOClass.IsConnected();
if (connStatus)
{
lblConnStatus.Text = "Connected";
unsafe
{
uint rez1 = 2;
uint* rez = &rez1;
string ctrName = "label" + btn_down.ToString();
if (SimpleIOClass.ReadPin(btn_down, rez))
{
if (rez1.ToString() == "1") // poga atlaista
{
// register button press
if (btn_down == Pogas["smaids"]) { OSD(":)"); new Thread(() => SendBtnToServer("1")).Start(); }
if (btn_down == Pogas["neitrals"]) { OSD(":|"); new Thread(() => SendBtnToServer("2")).Start(); }
if (btn_down == Pogas["bedigs"]) { OSD(":("); new Thread(() => SendBtnToServer("3")).Start(); }
if (btn_down == Pogas["smaids2"]) { OSD(":)"); new Thread(() => SendBtnToServer("1")).Start(); }
if (btn_down == Pogas["neitrals2"]) { OSD(":|"); new Thread(() => SendBtnToServer("2")).Start(); }
if (btn_down == Pogas["bedigs2"]) { OSD(":("); new Thread(() => SendBtnToServer("3")).Start(); }
}
}
else this.Controls[ctrName].Invoke(new Action(() => this.Controls[ctrName].Text = "Read pin ERROR (Release)"));
}
}
else
{
lblConnStatus.Text = "NOT Connected";
}
btn_down = 99;
}// CheckUserInput
Answer is: C# app is restarted every hour via Scheduled job. No more high cpu usage.