1

好的,我对编码和使用后台工作人员有点陌生,所以不要太苛刻地评判我。

基本上我正在催生一堆后台工作人员并让他们完成一项任务。问题是每个后台工作人员都在做同样的任务。我希望所有衍生的后台工作人员每个人都从事不同的任务,如果另一个后台工作人员已经完成了该任务,则忽略该任务。

这是我的后台工作人员做的工作子:

    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

我猜我的问题出在 for 循环中,但是如果没有它,我无法思考如何做到这一点,并使每个后台工作人员在不同的 URL 上工作。

4

1 回答 1

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;
    }
}
于 2013-09-10T06:45:00.400 回答