0

Хорошо, я немного новичок в кодировании и использовании фонового работника, поэтому не судите меня слишком сильно.Фоновый работник для Loop

В основном я рождаю группу работников фона и делаю им задачу. Проблема заключается в том, что каждый работник фона выполняет ту же задачу. Я хотел бы, чтобы все порожденные фоновые работники работали над другой задачей и игнорировали задачу, если другой фоновой работник сделал это.

вот мой фон работник сделать работу суб:

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 

Я предполагаю, что моя проблема в цикл, но я не могу постучать мой мозг вокруг, как это сделать без него и сделать каждый фоновая работа работника по другому URL-адресу.

ответ

1

Основная проблема, которую вы описываете, связана с синхронизацией - общая проблема при прошивке многопоточных приложений.

Одним из решений в вашем случае было бы создание очереди задач для выполнения и каждого рабочего рабочего рабочего в этой очереди. Когда фоновой работник получает рабочую запись из очереди, она будет удалена, поэтому не будет изменений другого работника фона, делающего то же самое.

В вашем случае у вас есть список URL-адресов, над которыми вы хотите работать. Добавьте эти URL-адреса в очередь. У фоновых работников будет цикл while, который будет получать следующую запись из очереди до тех пор, пока не будет оставлена ​​запись.

Ниже C# псевдо-код (я не говорю много VB.NET), но вы получите картину:

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 

Затем добавьте URL-адрес из вашей сетки в очередь, заблокировано

lock (workerURLsLock) 
    for (...) 
     workerURLs.Enqueue(...); 

После этого начните рабочий. В коде рабочего стола сделайте следующее:

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; 
    } 
} 
+0

Эй, спасибо, что помогает. Моя проблема теперь в том, что я не уверен, как передать строку gridview, над которой работает фоновый рабочий стол, поскольку она может вставлять данные обратно в сетку, например: DataGridViewX1.Rows (rowIndex) .Cells ("Status") .Value = «Working». Я буду следить за ним, но если бы у вас было какое-то представление об этом, это было бы потрясающе. –

+0

Конечно, вы можете не только добавить строку в 'Словарь', но и объекты. Вы можете создать небольшой вспомогательный класс, в котором есть член для URL-адреса и член типа 'DataGridViewRow'. Тогда у рабочего будет и то, и другое. В зависимости от версии фрейма вы также можете использовать 'Tuple '. Однако обратите внимание, что доступ к «DataGridViewRow» (т. Е. Изменение их значений) в операции поперечного потока может привести к ошибкам. Используйте 'this.Invoke', чтобы убедиться, что такие обновления выполняются в потоке графического интерфейса. –

+0

Спасибо за вашу помощь. Я закончил тем, что добавлял индексы в список в том же цикле, когда я добавил URL-адреса в синхронизированную очередь, все обновления пользовательского интерфейса выполняются в событии bgw_ProgressChanged, передавая индексы в качестве аргумента (что из чтения является правильным способом сделать это к моему пониманию.) Все, кажется, отлично работает. –

Смежные вопросы