5

そこで、リンクがアクセス可能かどうか (ライブ) をチェックするためのアプリケーションを作成します。私の質問は、スレッドを「常にビジー」にする方法です。つまり、アプリは 100 の異なる URL で 100 のスレッド (たとえば、FOR ループで作成) を実行します。そのため、スレッドの 1 つが終了すると、(URL が使用可能かどうかを確認して) 新しい URL を取得し、すぐに再開します。したがって、すべての URL がチェックされるまで、100 個のスレッドがノンストップで動作します。

どうすればそれを達成できますか?

4

3 に答える 3

10

あなたが探しているのはProducer-Consumer Modelと呼ばれるものです。チェックする URL のリストを含むリソースのプールがあり、1 つのスレッドがそのプールを埋めることができ、.NET 4 Parallel.ForEachがほとんどの作業を行う場合、消費者スレッドがそのプールからプルできます。

100 スレッドを使用することも、最適なスレッド数ではない可能性が非常に高く、タスク並列ライブラリにスレッド数を管理させてください。

以下は、リストが事前に入力され、スレッドの実行中にアイテムが追加されない場合の例です。

//Parallel.Foreach will block until it is done so you may want to run this function on a background worker.
public void StartThreads()
{
    List<string> myListOfUrls = GetUrls();

    Parallel.Foreach(myListOfUrls, ProcessUrl);
}


private void ProcessUrl(string url)
{
    //Do your work here, this code will be run from multiple threads.
}

実行時にコレクションにデータを入力する必要がある場合は、BlockingCollectionList<string>などの並行コレクションに置き換えます。

BlockingCollection<string> myListOfUrls = new BlockingCollection();

//Parallel.Foreach will block until it is done so you may want to run this function on a background worker.
public void StartThreads()
{
    if(myListOfUrls.IsComplete == true)
    {
        //The collection has emptied itself and you told it you where done using it, you will either need to throw a exception or make a new collection.
        //use IsCompleatedAdding to check to see if you told it that you are done with it, but there still may be members left to process.
        throw new InvalidOperationException();
    }

    //We create a Partitioner to remove the buffering behavior of Parallel.ForEach, this gives better performance with a BlockingCollection.
    var partitioner = Partitioner.Create(myListOfUrls.GetConsumingEnumerable(), EnumerablePartitionerOptions.NoBuffering);
    Parallel.ForEach(partitioner, ProcessUrl);
}

public void StopThreads()
{
    myListOfUrls.CompletedAdding()
}

public void AddUrl(string url)
{
    myListOfUrls.Add(url);
}

private void ProcessUrl(string url)
{
    //Do your work here, this code will be run from multiple threads.
}

また、自動化されたスレッドスケジューリングも最適ではない可能性があることを付け加えたいと思います。拡張できる制限がいくつかある可能性があります。元の質問のこのコメントを参照してください

100スレッドはひどい考えだと言った/賛成した人のために:私のデュアルコア2GB RAM XPマシンでは、Parallel.Foreachは(ThreadPool.SetMinThreadsを設定しない限り)5つ以上のスレッドを作成することはなく、100スレッドを作成すると常に〜30〜40%になりましたより高速な操作。したがって、すべてを Parallel.Foreach に任せないでください。PS: 私のテスト コード WebClient wc = new WebClient();var s = wc.DownloadString(url); (google のホームページ) – LB

于 2012-07-20T15:23:53.277 に答える
2

Parallel CTP のものを使用してください。含まれている parallel foreach メソッドは、まさにあなたが望むことを行います。

グーグルはあなたの友達です。

また、100 個のスレッドを使用することは、パフォーマンスにとって最適ではない可能性があります。使用可能なコアの数に関係なく使用します。

于 2012-07-20T15:23:46.493 に答える
0

ThreadPool処理する URL のリストを使用して渡してから、DoWorkそれらがライブかどうかのチェックをメソッドに処理させることができます。

 foreach (string s in URLs)
 {
       ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), s);
 }

 public void DoWork(object sender)
 {
       string url = (string)sender;
       //do stuff with url here
  }
于 2012-07-20T15:29:28.663 に答える