C#でパラメーターを使用してスレッドを開始するにはどうすればよいですか?
C#でパラメーターを使用してスレッドを開始するにはどうすればよいですか?
回答:
うん:
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
void MyParamObject(object myUrl){ //do stuff }
、パラメータタイプが必要ですobject
ParameterizedThreadStart
質問テキストからわかりやすく使用方法を知っていることを前提としているため、おそらくそうではありません。
スレッドコンストラクターの2つのオーバーロードの1つは、単一のパラメーターを開始メソッドに渡すことができる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) {
...
}
Dim thr As New Thread(Sub() DoStuff(settings))
ラムダ式を使用できます
private void MyMethod(string param1,int param2)
{
//do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
これはこれまでのところ私が見つけた最良の答えです、それは速くて簡単です。
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
パラメータタイプはオブジェクトである必要があります。
編集:
この答えは正しくありませんが、このアプローチはお勧めしません。ラムダ式を使用する方が読みやすく、型キャストを必要としません。こちらをご覧ください:https : //stackoverflow.com/a/1195915/52551
Parameter
ですか;) ?
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"
}
}
そのようにラムダを使用する簡単な方法..
Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
または、そのようにdelegate
使用することもできますThreadStart
...
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param4", "param5");
}
};
new Thread(ts).Start();
または、VS 2019 .NET 4.5以降を使用すると、さらにクリーンになります。
private void DoSomething(int param1, string param2)
{
//DO SOMETHING..
void ts()
{
if (param1 > 0) DoSomethingElse(param2, "param3");
}
new Thread(ts).Start();
//DO SOMETHING..
}
を使用しParametrizedThreadStart
ます。
ここですでにさまざまな回答で述べられているように、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();
したがって、この方法では、キャストを回避するだけで、スレッドにデータを提供するタイプセーフな方法があります;-)
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
不可能など)
if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
。とにかく、代わりに私が使用するビットがより快適見つけ、あなたのスレッドの方法を使用してのTasks<T>
、例えばのようにtasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
、(以下私の答えを参照stackoverflow.com/a/59777250/7586301を)
渡されたパラメーターに問題がありました。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;
}
ParametrizedThreadStartデリゲートを使用できます。
string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
BackgroundWorker RunWorkerAsyncメソッドを使用して、値を渡すことができます。
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`
}
}
のTask<T>
代わりに使用することを提案しThread
ます。それは複数のパラメータを許可し、本当にうまく実行されます。
これが実際の例です:
public static void Main()
{
List<Task> tasks = new List<Task>();
Console.WriteLine("Awaiting threads to finished...");
string par1 = "foo";
string par2 = "boo";
int par3 = 3;
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() => Calculate(par1, par2, par3)));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All threads finished!");
}
static bool Calculate1(string par1, string par2, int par3)
{
lock(_locker)
{
//...
return true;
}
}
// if need to lock, use this:
private static Object _locker = new Object();"
static bool Calculate2(string par1, string par2, int par3)
{
lock(_locker)
{
//...
return true;
}
}
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.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() + " ");
}
}
}
}