スレッドが終了する順序がわからないため、競合状態になります。
スレッドごとに個別のローカル変数を使用します。これは、先ほど で行った方法と同様に、スレッド コンストラクター内で割り当てますresponse
。
次に、次を使用してすべてのスレッドを待ち.Join()
ます。
t1.Join();
t2.Join();
t3.Join();
response
次に、すべてのJoin()
呼び出しが返された後に、ローカル変数を使用して設定します。
ただし、代わりにタスクを使用します。これが例です。これは、それぞれ異なる戻り値の型を持つ 3 つの異なるメソッドを別々のスレッドで実行します。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
private void run()
{
// Using tasks directly:
var task1 = Task<int>.Factory.StartNew(methodOne);
var task2 = Task<string>.Factory.StartNew(methodTwo);
var task3 = Task<double>.Factory.StartNew(methodThree);
// Alternatively:
// var task1 = Task.Run(new Func<int>(methodOne));
// var task2 = Task.Run(new Func<string>(methodTwo));
// var task3 = Task.Run(new Func<double>(methodThree));
string result = string.Format
(
"Task 1: {0}, Task 2: {1}, Task 3: {2}",
task1.Result, // Accessing Task.Result automatically
task2.Result, // waits for the task to complete.
task3.Result
);
Console.WriteLine(result);
// Alternatively, you can use tasks indirectly via Parallel.Invoke().
// You might find this more readable and less typing:
int r1 = 0;
string r2 = null;
double r3 = 0;
Parallel.Invoke
(
() => r1 = methodOne(),
() => r2 = methodTwo(),
() => r3 = methodThree()
);
result = string.Format
(
"Task 1: {0}, Task 2: {1}, Task 3: {2}",
r1,
r2,
r3
);
Console.WriteLine(result);
}
static int methodOne()
{
Thread.Sleep(1000);
return 1;
}
static string methodTwo()
{
Thread.Sleep(750);
return "two";
}
static double methodThree()
{
Thread.Sleep(500);
return 3.0;
}
static void Main(string[] args)
{
new Program().run();
}
}
}
どちらのアプローチを取るにしても、重要なことは、結果をスレッドまたはタスク内に直接割り当てないことです。response
すべてのスレッドまたはタスクが終了するまで待ってから、結果を に割り当ててresponse
ください。