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.
Related
I currently have a application that pings a list of IPs.
The user clicks a button and it continuously pings all IPS for 20 seconds..
What I want to do is click a button to stop this.
I created a function i called "Process" and it calls this process when the button is clicked.
I tried to create a bool value and while loop for when it's false and made the stop button change the bool value to true, but it doesn't seem to stop anything, in fact I can't even close the window until the ping is completed.
My code is below.
private bool _stopLoop;
private void btnPlay_Click(object sender, EventArgs e)
{
Process();
}
private void Process()
{
while (_stopLoop == false)
{
for (int i = 0; i < 20; i++)
{
foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows)
{
var count = 20;
progressBar1.Value = i * progressBar1.Maximum / count;
Application.DoEvents();
var url = dataGridView1Row.Cells[1].Value.ToString();
int timeout = 500;
Ping ping = new Ping();
PingReply pingreply = ping.Send(url, timeout);
PingReply result = null;
IPStatus status;
result = pingreply;
status = result.Status;
if (status != IPStatus.Success)
{
dataGridView1Row.Cells[0].Style.BackColor = Color.Red;
dataGridView1Row.Cells[0].Value = "Offline";
}
else
{
dataGridView1Row.Cells[0].Style.BackColor = Color.Green;
dataGridView1Row.Cells[0].Value = "Online";
}
}
}
}
}
private void btnStop_Click(object sender, EventArgs e)
{
_stopLoop = true;
}
I am only targeting the direct questions why the loops dont stop. Implementing a background thread or tasks or background worker is a better solution but not the question :)
As in my comment states, you only break out of your "infinite" loop which is the most outer loop.
The two inner loops which run over your IP's ( foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows){ [...] } as well as your "do it for 20 times" loops for (int i = 0; i < 20; i++){ [...] } need to be broken out of if you want it to stop.
this means you can change them like that:
while (_stopLoop == false)
{
for (int i = 0; i < 20; i++)
{
foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows)
{
if(_stopLoop)
return; // finish execution and jump out of all loops, or use break to jump into the for loop, but then you need to break out of it as well
/* your ping logic */
}
}
}
If you use async/await your GUI can be responsive and your requests can be concurrent at the same time:
private CancellationTokenSource pingCancellation;
private async void btnPlay_Click(object sender, EventArgs e)
{
const int pingTimeout = 500;
var pingDuration = TimeSpan.FromSeconds(20);
btnPlay.Enabled = false;
dataGridView1.ReadOnly = true;
var entries =
dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(r => !r.IsNewRow)
.Select(row => new { Row = row, Hostname = row.Cells[1].Value.ToString(), Ping = new Ping() })
.ToList();
pingCancellation = new CancellationTokenSource();
pingCancellation.Token.Register(() => entries.ForEach(e => e.Ping.SendAsyncCancel()));
btnStop.Enabled = true;
pingCancellation.CancelAfter(pingDuration);
var finishTime = DateTime.UtcNow.Add(pingDuration);
try
{
while (!pingCancellation.IsCancellationRequested)
{
await Task.WhenAll(entries.Select(async e =>
{
var result = await e.Ping.SendPingAsync(e.Hostname, pingTimeout);
if (result.Status != IPStatus.Success)
{
e.Row.Cells[0].Style.BackColor = Color.Red;
e.Row.Cells[0].Value = "Offline";
}
else
{
e.Row.Cells[0].Style.BackColor = Color.Green;
e.Row.Cells[0].Value = "Online";
}
}).Concat(new[] { Task.Delay(pingTimeout, pingCancellation.Token) /*Rate limiting*/ }));
progressBar1.Value = (int)Math.Min(progressBar1.Maximum * (pingDuration - (finishTime - DateTime.UtcNow)).Ticks / pingDuration.Ticks, progressBar1.Maximum);
}
}
catch (TaskCanceledException)
{
}
btnStop.Enabled = false;
pingCancellation.Dispose();
pingCancellation = null;
foreach (var entry in entries)
{
entry.Ping.Dispose();
}
progressBar1.Value = 0;
dataGridView1.ReadOnly = false;
btnPlay.Enabled = true;
}
private void btnStop_Click(object sender, EventArgs e)
{
if (pingCancellation != null && !pingCancellation.IsCancellationRequested)
{
pingCancellation.Cancel();
}
}
My requirement is to insert item in a queue and process it but the items should be added first and after a while they should be processed (as some other things needs to be set before processing the items. Here is the coding I have done so far.
#region Variables Declarations
private Thread threadTask = null;
ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>();
string currentSeqNo;
string previousSeqNo = "-1";
#endregion
private void test1_Load(object sender, EventArgs e)
{
AddItems();
if (threadTask == null)
{
threadTask = new Thread(Kick);
Thread.Sleep(5000);
threadTask.Start();
}
}
private void AddItems()
{
for (Int64 i = 100000; i < 300000; i++)
{
concurrentQueue.Enqueue(i.ToString());
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = i.ToString();
label1.Update();
}));
}
}
private void Kick()
{
while (true)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
RemoveItems();
}
}
}
private void RemoveItems()
{
string item;
while (concurrentQueue.TryDequeue(out item))
{
this.Invoke(new MethodInvoker(delegate()
{
label2.Text = item;
label2.Update();
}));
currentSeqNo = item; // second time does not start wil 100000
if (previousSeqNo != "-1")
{
if (long.Parse(currentSeqNo) != long.Parse(previousSeqNo) + 1)
{
Reconnect();
}
else
{
//Process item
previousSeqNo = currentSeqNo;
}
}
else
{
//Process item
previousSeqNo = currentSeqNo;
}
}
}
private void Reconnect()
{
currentSeqNo = "";
previousSeqNo = "-1";
string someItem;
while (concurrentQueue.Count > 0)
{
concurrentQueue.TryDequeue(out someItem);
}
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = "";
label2.Text = "";
label1.Update();
label2.Update();
}));
AddItems();
if (threadTask == null)
{
threadTask = new Thread(Kick);
threadTask.Start();
}
}
private void button1_Click_1(object sender, EventArgs e)
{
Reconnect();
}
To reproduce the issue: Run the app and in the middle click on the button. Now the queue should again be started from 100000 but it shows the number somewhere greater than 100000.
Please advise how do I release all the resources to make a fresh start after clicking a button. Though I am setting them to default and also clearing the queue but it still shows the old values in currentSeqNo when 'RemoveItems' method is called.
What you see is a race condition between the Kick thread and the button click handler. When you press the button you execute Reconnect() in it you clean the queue and then call the AddItems() function. But all this time the Kick function tries to Dequeue and so you end up each time with an arbitrary amount of items in it. What you should do is to synchronize between these functions or prevent the Kick from executing while you are adding items.
Couple of comments:
1) You Kick() method have an infinite loop, that too without sleep. Every thread started will keep on running as you didn't have a scope for thread to come out.
You can have a member variable like bKeepRunning with default value as true. Set that variable to false in beginning of Reconnect() function. Something like:
private void Kick()
{
while (bKeepRunning)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
RemoveItems();
}
}
}
Why do you have Thread.Sleep(5000); in test1_Load()? I dont think that is needed.
I made small change in your code, something like:
private void AddItems()
{
for (Int64 i = 100000; i < 300000; i++)
{
concurrentQueue.Enqueue(i.ToString());
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = i.ToString();
label1.Update();
}));
if (i < 100004)
Thread.Sleep(1000);
}
}
private void Kick()
{
while (bKeepRunning)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
RemoveItems();
}
}
}
private void Reconnect()
{
currentSeqNo = "";
previousSeqNo = "-1";
bKeepRunning = false;
threadTask = null;
string someItem;
while (concurrentQueue.Count > 0)
{
concurrentQueue.TryDequeue(out someItem);
}
this.Invoke(new MethodInvoker(delegate()
{
label1.Text = "";
label2.Text = "";
label1.Update();
label2.Update();
}));
Thread.Sleep(2000);
AddItems();
bKeepRunning = true;
if (threadTask == null)
{
threadTask = new Thread(Kick);
threadTask.Start();
}
}
It helped me to see that value is starting from 100000. You can try the same at your end.
Note: I have stopped thread and restarted after clicking on button. Hence i dont see any flaw in your code as such. It just runs fast so that you are not able to realize start values.
You should make UI thread and threadTask thread sync, just use ManualResetEventSlim Signal Construct to, like this:
static ManualResetEventSlim guard = new ManualResetEventSlim(true);
private void button1_Click_1(object sender, EventArgs e)
{
guard.Reset();
Reconnect();
guard.Set();
}
private void RemoveItems()
{
string item;
while (concurrentQueue.TryDequeue(out item))
{
guard.Wait();
//......
}
}
see:
ManualResetEventSlim Class
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.
I do have a problem with a multithreaded TCPClient application, every Client object has a Thread that recievies and sends messages and a thread that handle the Tasks that should be handled (depending on the messages)... (for example creates and answer that the msg threads sends). But something is going wrong... the application almost allways uses 100% cpu (if any thread have a task, and thats most of the time). I also have a feeling that some threads get prioritised less then others (can see in some loggs that an operation takes longer in thread 1 then in thread 2 for exampel... Is there any nice way to handel this problem?
I would love some help or some hints!
Anything unclear just ask :)
Thanks! /Nick
//Waiting for TCP-connections and creating them as they arrive. Starts a Thread that handles the messages recieved and sent with this thread.
private void ListenForClients()
{
try
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
Connection c = new Connection(this.parent);
connectionCollection.Add(c);
Thread clientThread = new Thread(new ParameterizedThreadStart(c.HandleClientComm));
threadCollection.Add(clientThread);
clientThread.Start(client);
}
}
catch (Exception e)
{
}
}
//Connection constructor, creates a ToDo-thread, this handles the messages (DB, Filewriting etc.) recieived and creats new ones to be sent.
public Connection()
{
this.todo = new ArrayList();
todoT = new Thread(handleToDo);
todoT.Start();
}
//Messagehandeling-thread
public void HandleClientComm(object client)
{
try
{
TcpClient server = (TcpClient)client;
NetworkStream ns = server.GetStream();
byte[] data = new byte[1024];
string input, stringData;
online = true;
DateTime lastTime = DateTime.Now;
while (true && this.online)
{
try
{
if (lastTime.AddMinutes(2) < DateTime.Now)
break;
data = new byte[1024];
if (ns.DataAvailable && ns.CanRead)
{
int recv = ns.Read(data, 0, data.Length);
if (recv > 0)
{
lastTime = DateTime.Now;
if ((byte)data[recv - 1] == (byte)255)
{
int cnt = -1;
for (int i = 0; i < recv; i++)
{
if (data[i] == (byte)254)
{
cnt = i;
break;
}
}
int nr = recv - cnt - 2;
byte[] tmp = new byte[nr];
for (int i = 0; i < nr; i++)
{
tmp[i] = data[cnt + i + 1];
}
string crc = Encoding.UTF8.GetString(tmp);
stringData = Encoding.UTF8.GetString(data, 0, cnt);
MsgStruct msgs = new MsgStruct(stringData);
msgs.setCrc(crc);
addTodo(msgs);
if (msgs.getMsg()[0] == 'T' && this.type == 1)
this.parent.cStructHandler.sendAck(msgs, this.ID);
Console.WriteLine(todo.Count);
}
}
}
if (parent.cStructHandler.gotMsg(this.ID))
{
MsgStruct tmpCs = parent.cStructHandler.getNextMsg(this.ID);
if (tmpCs.getMsg().Length != 0 && ns.CanWrite)
{
byte[] ba = Encoding.UTF8.GetBytes(tmpCs.getMsg());
if (tmpCs.getCrc() == "")
{
ulong tmp = CRC.calc_crc(ba, ba.Length);
tmpCs.setCrc(tmp.ToString("X"));
}
if (tmpCs.canSendByTimeout())
{
string crcStr = "?" + tmpCs.getCrc() + "?";
byte[] bb = Encoding.UTF8.GetBytes(crcStr);
crcStr = Encoding.UTF8.GetString(bb);
byte[] fullMsg = new byte[ba.Length + bb.Length];
bb[0] = 254;
bb[bb.Length - 1] = 255;
ba.CopyTo(fullMsg, 0);
bb.CopyTo(fullMsg, ba.Length);
string s = System.Text.UTF8Encoding.ASCII.GetString(fullMsg);
ns.Write(fullMsg, 0, fullMsg.Length);
if (!tmpCs.isAckNeeded())
parent.cStructHandler.removeNextMsg(this.ID);
}
}
}
}
catch (Exception e)
{
break;
}
}
ns.Close();
server.Close();
dead = true;
}
catch (Exception e)
{
dead = true;
}
}
//Todo-thread
public void handleToDo()
{
try
{
int cnt = 0;
while (true)
{
if (todo.Count > 0)
{
//SWITCH CASE FOR DIFFERENT MESSAGE TYPES, DOING TASKS DEPENDING ON WHAT ONES...
}
else
{
if (dead)
{
todoT.Abort();
todoT = null;
break;
}
}
}
}
}
Stop checking if data is available etc. and just let the read() block. That's how it's supposed to work!
If you want to write stuff to the socket, do it from another thread, (direct from parent thingy?), or change your design to use async reads/writes.
Looping around, polling stuff, sleep() etc. is just a waste of CPU and/or adding avoidable latency to your app.
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.