あなたの質問によると...
C#でThread.ThreadStart()メソッドにパラメーターを渡す方法は?
...そして発生したエラーは、コードを修正する必要があります
Thread thread = new Thread(new ThreadStart(download(filename));
に
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
ただし、問題は最初は思われるほど複雑になります。
Thread
現在、クラス(4.7.2)は、いくつか提供コンストラクタとStart
過負荷と方法。
この質問に関連するこれらのコンストラクタは次のとおりです。
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
のスレッドの方法。
ただし、このアプローチには大きな問題が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
などの汎用デリゲートを取得することを期待します。残念ながら、このようなものは存在しません(まだ?)。ParameterizedThreadStart<T>
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();
したがって、この方法では、キャストを回避するだけで、スレッドにデータを提供するタイプセーフな方法があります;-)