Reputation: 2237
Ok I am a bit new to coding and using the backgroundworker so don't judge me too hard.
Basically i am spawning a bunch of background workers and having them do a task. The problem is each background worker is doing the same task. I would like all the spawned background workers to each work on a different task and ignore the task if another background worker has alreday done it.
here is my background worker do work sub:
Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Threading.Thread.Sleep(5000)
Dim bgw As BackgroundWorker = DirectCast(sender, BackgroundWorker)
Dim url As String
Dim pr As Integer
Dim prproxy As Integer
Dim randomLine As Integer
For rowIndex = 0 To DataGridViewX1.RowCount - 1
DataGridViewX1.Rows(rowIndex).Cells("Status").Value = "Working"
url = DataGridViewX1.Rows(rowIndex).Cells("url").Value.ToString
If SwitchButton1.Value = True Then 'check page rank if proxies are enabled.
randomLine = RandomNumbers.Next(proxies.TextBoxX1.Lines.Length)
Dim s As String = proxies.TextBoxX1.Lines(randomLine)
RandomProxy = Split(s, ":", , CompareMethod.Text)
pr = PageRank.GooglePageRank.GetPageRankWithProxy(url, RandomProxy(0), RandomProxy(1))
DataGridViewX1.Rows(rowIndex).Cells("proxy").Value = RandomProxy(0) & ":" & RandomProxy(1)
Else
pr = PageRank.GooglePageRank.GetPageRank(url) 'If proxies are not enabled do this.
End If
DataGridViewX1.Rows(rowIndex).Cells("PR").Value = pr
DataGridViewX1.Rows(rowIndex).Cells("Status").Value = "Done"
Next
End Sub
I'm guessing my problem is in the for loop, but I can't rap my brain around how to do this without it and make each background worker work on a different URL.
Upvotes: 0
Views: 1423
Reputation: 56697
The basic problem you're describing has to do with synchronization - a common problem when progrmming multi-threaded applications.
One solution in your case would be to create a queue of tasks to fulfill and have each background worker work on that queue. When a background worker gets a work entry from the queue, it would be removed so there would not be a change of another background worker doing the same thing.
In your case you seem to have a list of URLs which you want to work on. Add these URLs to a queue. The background workers would have a while
loop fetching the next entry from the queue until there is no entry left.
The following is C# pseudo-code (I don't speak much VB.NET), but you'll get the picture:
private Queue<string> workerURLs = new Queue<string>(); // this would be a member of the class
private object workerURLsLock = "LOCK"; // This is also a member of the class
Then, add the URLs from your grid to the queue, locked
lock (workerURLsLock)
for (...)
workerURLs.Enqueue(...);
After that, start the workers. In the background worker's code, do this:
bool workToDo = true;
while (workToDo)
{
string nextUrl = "";
lock (workerURLsLock) // IMPORTANT!! LET NO OTHER THREAD MODIFY THE QUEUE
{
nextUrl = workerURLs.Dequeue();
}
if (!String.IsNullOrWhitespace(nextUrl))
{
// Do the work
}
else
{
workToDo = false;
}
}
Upvotes: 1