0

私はこのような機能を持っています:

private void GetRSS(int start, int end)
{
    for (int i = start; i < end; i++)
    {
        string content = string.Empty;
        using (WebClient client = new WebClient())
        {
            //some code here get html content
        }
        // some code here parse content
    }
}

必要なすべてのデータを取得するための実行時間を最小限に抑えるために、関数を異なる範囲で同時に 4 回実行してから、結果をマージするか、スレッド セーフ リストまたは辞書を使用したいと考えています。

私の質問は、どうすればこの関数を 4 つの別々のスレッドで実行し、スレッドの 1 つがまだ機能しているかどうかを制御できるか、いつ終了するかを知ることができないかということです。

私の最初のアイデアは、各スレッドを宣言することでした:

private Thread _controler;
private Thread _worker1;
private Thread _worker2;
private Thread _worker3;
private Thread _worker4;
private bool _isRunning = false;

次に、コントローラーを起動し、コントローラー内から各スレッドを呼び出して上記の関数を実行し、コントローラーからの各スレッドを追跡します。次のようになります。

private void _ControlerStart()
{
    _worker1 = new Thread(GetRSS);
    try
    {
        _worker1.Start(1, 7711);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
    // repeat the above to all the 4 threads
    _isRunning = true;
    while (_isRunning)
    {
        if (_worker1.ThreadState != ThreadState.Running && _worker2.ThreadState != ThreadState.Running && _worker3.ThreadState != ThreadState.Running && _worker4.ThreadState != ThreadState.Running)
            _isRunning = false;
    }
    MessageBox.Show("Done");
}

上記のすべての混乱について考えていると、これは私が望んでいたことを行うための最良の方法ではないことに気付き、ここにいます;)。

複数のスレッドを管理して同じ関数を実行しながら、各スレッドがデータを閉じたり、保存したり、マージしたりする作業をいつ終了したかを知ることができるようにするにはどうすればよいでしょうか。

4

3 に答える 3

3
private static void GetRSS(int start, int end)
{
    var bunchSize = (end - start) / 4 + 1;

    var threads = new List<Thread>();

    for (int i = 0; i < 4; i++)
    {
        var currStart = start + i * bunchSize;
        var currEnd = currStart + bunchSize;

        if (currEnd > end)
        {
            currEnd = end;
        }

        var thread = new Thread(() =>
                                    {
                                        // thread logic using currStart and currEnd

                                        string content = string.Empty;
                                        using (WebClient client = new WebClient())
                                        {
                                            //some code here get html content
                                        }
                                        // some code here parse content
                                    });

        threads.Add(thread);
        thread.Start();
    }

    foreach (var thread in threads)
    {
        thread.Join();
    }
}
于 2012-05-27T04:47:20.650 に答える
1

TPL を使用しない特定の理由はありますか? http://msdn.microsoft.com/en-us/library/dd460717.aspx

お気づきかもしれませんが、提供されたコードの問題は、それが宣言的でないことです。あなたがやりたいことではなく、それを行う方法を機械に伝えているのです。

編集私のコメントでは、次のコードを使用することを提案しました。

OPのコメントで、私は見ました

各ページに10個のレコードがある場所を取得する30kページがあるため、30kページを4つのスレッドに分割し、各ページを文字列にダウンロードした後に解析する必要があります

最初の部分は実行するアクションを定義し、2 番目の部分は PC の持ち方を明確に記述します。私が提案しているのは、PC の手を握るのをやめて、実行すべき高レベルのアクションの観点から考えることです。

  1. Nページを求める
  2. いずれかのページが利用可能になったら、結果を消費します
  3. N ページすべてが使用可能になり、消費されたら、その結果を照合します

これには、非同期プログラミングが必要です。.NET 4.0 では、主に F# 2.0 で使用できます。C# 4.0 は継続で APM を使用できますが、お勧めしません。

C# vNext はこれをサポートしています。VS 2012 を参照してください。

于 2012-05-27T04:35:18.640 に答える
0

タスクの方法では、TaskFactory.ContinueWhenAll メソッドを使用して、すべてのタスクが完了したときに何らかのアクションを実行できます。

    private void ButtonOnClick(object sender, RoutedEventArgs routedEventArgs) {
        const int n = 15;
        var tasks = new Task<int>[n];
        for (int i = 0; i < n; i++) {
            tasks[i] = Task.Factory.StartNew(
                () => {
                    Thread.Sleep(500);
                    return 100;
                });
        }

        Task.Factory.ContinueWhenAll(
            tasks,
            ts => { text.Text = string.Format("Sum: {0}", ts.Sum(task => task.Result)); },
            CancellationToken.None,
            TaskContinuationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext());
    }

ここでは、UI スレッドで継続タスクを実行するためにTaskScheduler.FromCurrentSynchronizationContext()を使用しています。

于 2012-05-27T09:36:49.200 に答える