web-dev-qa-db-ja.com

パラメータ付きThreadStart

どのようにしてC#のパラメータでスレッドを始めますか?

238
JL.

うん:

Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
156
Erick

Threadコンストラクタの2つのオーバーロードのうちの1つは、単一のパラメータをstartメソッドに渡すことを可能にするParameterizedThreadStartデリゲートを受け取ります。残念ながらそれはただ一つのパラメータを許容し、それがオブジェクトとしてそれを渡すので安全でない方法でそうします。ラムダ式を使用して関連パラメータを取得し、厳密に型指定された方法で渡す方がはるかに簡単です。

以下を試してください

public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
  var t = new Thread(() => RealStart(param1, param2));
  t.Start();
  return t;
}

private static void RealStart(SomeType param1, SomeOtherType param2) {
  ...
}
443
JaredPar

ラムダ式を使うことができます

private void MyMethod(string param1,int param2)
{
  //do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();

これは私が見つけることができる今のところ最高の答えです、それは速くて簡単です。

119
Georgi-it
Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param)
{
    string Parameter = (string)param;
}

パラメータタイプはオブジェクトでなければなりません。

編集:

この答えは正しくありませんが、私はこのアプローチに対してはお勧めしません。ラムダ式を使用すると読みやすくなり、型キャストが不要になります。こちらを参照してください。 https://stackoverflow.com/a/1195915/52551

34
Spencer Ruport
class Program
{
    static void Main(string[] args)
    {
        Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));

        t.Start("My Parameter");
    }

    static void ThreadMethod(object parameter)
    {
        // parameter equals to "My Parameter"
    }
}
29
huseyint

こんなラムダを使った簡単な方法..

Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();

ORあなたはdelegateを使ってThreadStartさえできます...

ThreadStart ts = delegate
{
     bool moreWork = DoWork("param1", "param2", "param3");
     if (moreWork) 
     {
          DoMoreWork("param1", "param2");
     }
};
new Thread(ts).Start();
23
Master Mick

ParameterizedThreadStart を使用してください。

8
Justin Niessner

ParametrizedThreadStart を使用してください。

8
Thomas

渡されたパラメータに問題がありました。 forループから整数を関数に渡して表示しましたが、常に異なる結果が出ました。 ParametrizedThreadStartと(1,2,2,3)(1,2,3,3)(1,1,2,3)などのように委任.

この単純なコードは魅力として働きました

Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param) 
{
 string Parameter = (string)param; 
}
5
user3805007

ParameterizedThreadStartは1つのパラメータを取ります。これを使用して、1つのパラメータ、または複数のプロパティを含むカスタムクラスを送信できます。

もう1つの方法は、インスタンスメンバーとして起動するメソッドを、設定するパラメータのプロパティと共にクラスに配置することです。クラスのインスタンスを作成し、プロパティを設定し、インスタンスとメソッドを指定してスレッドを起動すると、メソッドはプロパティにアクセスできます。

4
Guffa

あなたは ParametrizedThreadStart デリゲートを使うことができます:

string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
3
CMS

BackgroundWorkerRunWorkerAsync メソッドを使用して値を渡すことができます。

3
SwDevMan81
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {

            int x = 10;
            Thread t1 =new Thread(new ParameterizedThreadStart(order1));
            t1.IsBackground = true;//i can stope 
            t1.Start(x);

            Thread t2=new Thread(order2);
            t2.Priority = ThreadPriority.Highest;
            t2.Start();

            Console.ReadKey();
        }//Main

        static void  order1(object args)
        {
            int x = (int)args;


                for (int i = 0; i < x; i++)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write(i.ToString() + " ");
            }
        }

        static void order2()
        {
            for (int i = 100; i > 0; i--)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write(i.ToString() + " ");
            }
        }`enter code here`
    }
}

ここでさまざまな回答ですでに言及されているように、 Thread クラスは現在(4.7.2)いくつかの constructorsStart メソッドをオーバーロードとともに提供します。

この質問に関連するこれらのコンストラクタは次のとおりです。

public Thread(ThreadStart start);

そして

public Thread(ParameterizedThreadStart start);

ThreadStart デリゲートまたは ParameterizedThreadStart デリゲートを使用します。

対応するデリゲートは次のようになります。

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);

ご覧のとおり、使用する正しいコンストラクターはParameterizedThreadStartデリゲートを取得するコンストラクターであるため、スレッドによって指定されたデリゲートのシグネチャに準拠するメソッドを開始できます。

Threadクラスをインスタンス化する簡単な例は次のようになります

Thread thread = new Thread(new ParameterizedThreadStart(Work));

あるいは単に

Thread thread = new Thread(Work);

対応するメソッドのシグネチャ(この例ではWorkと呼ばれます)は次のようになります。

private void Work(object data)
{
   ...
}

残っているのは、スレッドを開始することです。これは、次のいずれかを使用して行われます

public void Start();

または

public void Start(object parameter);

Start()はスレッドを開始し、nullをデータとしてメソッドに渡しますが、Start(...)を使用して、スレッドのWorkメソッドにanythingを渡すことができます。

ただし、このアプローチには1つの大きな問題があります。Workメソッドに渡されるものはすべてオブジェクトにキャストされます。つまり、Workメソッド内では、次の例のように元の型に再度キャストする必要があります。

public static void Main(string[] args)
{
    Thread thread = new Thread(Work);

    thread.Start("I've got some text");
    Console.ReadLine();
}

private static void Work(object data)
{
    string message = (string)data; // Wow, this is ugly

    Console.WriteLine($"I, the thread write: {message}");
}



キャスティングは、通常はしたくないことです。

文字列以外の何かを誰かが渡すとどうなりますか?これは最初は不可能だと思われるため(が私のメソッドであるため、私は何をするかを知っていますまたはこのメソッドはプライベートです。それに何かを渡すには?)場合によっては問題にならないこともあれば、問題になることもあります。このような場合、おそらく InvalidCastException になりますが、これはおそらくスレッドを終了するだけなので、おそらく気付かないでしょう。

解決策として、ParameterizedThreadStart<T>のような汎用ParameterizedThreadStartデリゲートを取得します。ここで、Tは、Workメソッドに渡すデータのタイプです。残念ながら、このようなものは存在しません(まだ?)。

ただし、この問題には 推奨ソリューション があります。スレッドに渡されるデータと、次のようなワーカーメソッドを表すメソッドの両方を含むクラスを作成する必要があります。

public class ThreadWithState
{
    private string message;

    public ThreadWithState(string message)
    {
        this.message = message;
    }

    public void Work()
    {
        Console.WriteLine($"I, the thread write: {this.message}");
    }
}

このアプローチでは、次のようにスレッドを開始します。

ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);

thread.Start();

したがって、この方法では、単にキャストすることを避け、スレッドにデータを提供するタイプセーフな方法があります;-)

0
Markus Safar