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

あなたが説明している基本的な問題は、マルチスレッドアプリケーションをプログラムするときの一般的な問題である同期に関係しています。

あなたの場合の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 に答える