0

XmlNodeListをループして、そこからデータを取得し、このデータを使用する新しいスレッドを開始しようとしています。

これが私がこれまでに持っているものです:

    public void startRun(string kwd)
    {
        doRun run = new doRun();
        run.run(kwd);
    }

    private void startBtn_Click(object sender, EventArgs e)
    {
        XmlDocument searches = new XmlDocument();
        searches.Load("data\\Searches.xml");

        XmlNodeList search = searches.SelectNodes("Searches/search");
        var nodeCount = search.Count;

        for(var i = 0; i < nodeCount; i++)
        {
            string kwd = System.Uri.EscapeDataString(search[i].SelectSingleNode("query").InnerText);
            doRun run = new doRun(this);
            Thread newThread = new Thread( new ThreadStart( startRun(kwd) ) );
        }
    }

これはまったくうまくいきません。Visual StudioはMethod name expected、この行について次のように述べています。

Thread newThread = new Thread( new ThreadStart( startRun(kwd) ) );

このパラメータを新しいtheadに渡すにはどうすればよいですか?

4

1 に答える 1

1

あなたのアプローチにはいくつかの問題があります:

デリゲートを作成するための構文から始めるのは間違っています:new ThreadStart(startRun(kwd))は有効な構文ではありません。適切な構文は次のとおりです。-new ThreadStart(startRun)メソッド名のみを使用します。

次に、パラメーターをスレッドに渡す場合は、 ThreadStartデリゲートの代わりにParameterizedThreadStartデリゲートを使用する必要があります。

Thread newThread = new Thread( new ParameterizedThreadStart(startRun));

そして、:への呼び出しでスレッドを開始しますStart(...)

newThread.Start(kwd);

また、の署名でstartRunは、パラメータで文字列ではなくオブジェクトを使用する必要があります。

public void startRun(object kwdObject)

内部では、キャストkwdstringて使用できます。

public void startRun(object kwdObject)
{
    string kwd = (string)kwdObject;
    // continue to do work..

さて、の実装に関してはstartRun、メソッド自体が冗長であるように思われます。(ちなみに、クラス名の最初の文字を大文字にすることをお勧めします)というクラスがある場合は、doRundoRunのrunメソッドをThreadStartデリゲートとして使用しないのはなぜですか。doRun.run(..)がオブジェクトを受け取らない場合を除いて、その場合、転送関数を作成するアプローチは問題ありません。

doRun run = new doRun();
run.run(kwd);

パート2

コードの問題をそのままカバーしたので、実行中のタスクが長時間実行タスクでない場合(つまり、期待する場合)、タスクを実行するために新しいスレッドを手動で作成するのではなく、ThreadPoolワーカースレッドを使用することを検討することをお勧めします数秒以内に完了するタスク)。

そのためには、次のようにコードを変更できます。

  for(var i = 0; i < nodeCount; i++)
  {
      string kwd = System.Uri.EscapeDataString(search[i].SelectSingleNode("query").InnerText);
      ThreadPool.QueUserWorkItem((WaitCallback)startRun, kwd);
  }

パート3

ThreadPoolスレッドを使用した、完全に機能する例:

public void startRun(object kwd)
{
    doRun run = new doRun();
    run.run((string)kwd);
}

private void startBtn_Click(object sender, EventArgs e)
{
    XmlDocument searches = new XmlDocument();
    searches.Load("data\\Searches.xml");

    XmlNodeList search = searches.SelectNodes("Searches/search");
    var nodeCount = search.Count;

    for(var i = 0; i < nodeCount; i++)
    {
        string kwd = System.Uri.EscapeDataString(search[i].SelectSingleNode("query").InnerText);

        ThreadPool.QueueUserWorkItem((WaitCallback)startRun, kwd);
        // replace line above with the following two lines if you want to use regular threads
        //  Thread newThread = new Thread((ParameterizedThreadStart)startRun);
        //  newThread.Start(kwd);
    }
}
于 2013-03-14T18:49:24.733 に答える