【发布时间】:2010-12-19 23:35:22
【问题描述】:
我在网上看到它说我使用myThread.Join(); 当我想阻塞我的线程直到另一个线程完成时。 (我不明白的一件事是如果我有多个线程会怎样)。
但一般来说,我只是不明白何时使用.Join() 或它有用的条件。谁能像我四年级一样向我解释一下?非常简单易懂的解释会得到我的回答投票。
【问题讨论】:
标签: c# multithreading
我在网上看到它说我使用myThread.Join(); 当我想阻塞我的线程直到另一个线程完成时。 (我不明白的一件事是如果我有多个线程会怎样)。
但一般来说,我只是不明白何时使用.Join() 或它有用的条件。谁能像我四年级一样向我解释一下?非常简单易懂的解释会得到我的回答投票。
【问题讨论】:
标签: c# multithreading
假设您想启动一些工作线程来执行某种计算,然后对所有结果执行一些操作。
List<Thread> workerThreads = new List<Thread>();
List<int> results = new List<int>();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(() => {
Thread.Sleep(new Random().Next(1000, 5000));
lock (results) {
results.Add(new Random().Next(1, 10));
}
});
workerThreads.Add(thread);
thread.Start();
}
// Wait for all the threads to finish so that the results list is populated.
// If a thread is already finished when Join is called, Join will return immediately.
foreach (Thread thread in workerThreads) {
thread.Join();
}
Debug.WriteLine("Sum of results: " + results.Sum());
哦,是的,不要像那样使用 Random,我只是想写一个简单易懂的例子。如果您在时间上太接近创建新的 Random 实例,它最终并不是真正随机的,因为种子是基于时钟的。
【讨论】:
在下面的代码 sn-p 中,主线程调用 Join() 导致它等待所有派生线程完成:
static void Main()
{
Thread regularThread = new Thread(ThreadMethod);
regularThread.Start();
Thread regularThread2 = new Thread(ThreadMethod2);
regularThread2.Start();
// Wait for spawned threads to end.
regularThread.Join();
Console.WriteLine("regularThread returned.");
regularThread2.Join();
Console.WriteLine("regularThread2 returned.");
}
请注意,如果您还从线程池中启动了一个线程(例如使用 QueueUserWorkItem),Join 将不会等待该后台线程。您需要实现一些其他机制,例如使用 AutoResetEvent。
有关线程的精彩介绍,我建议阅读 Joe Albahari 的免费 Threading in C#
【讨论】:
这是一个非常简单的程序,用于演示线程Join的用法。请关注我的cmets以便更好地理解。按原样编写此程序。
using System;
using System.Threading;
namespace ThreadSample
{
class Program
{
static Thread thread1, thread2;
static int sum=0;
static void Main(string[] args)
{
start();
Console.ReadKey();
}
private static void Sample() { sum = sum + 1; }
private static void Sample2() { sum = sum + 10; }
private static void start()
{
thread1 = new Thread(new ThreadStart(Sample));
thread2 = new Thread(new ThreadStart(Sample2));
thread1.Start();
thread2.Start();
// thread1.Join();
// thread2.Join();
Console.WriteLine(sum);
Console.WriteLine();
}
}
}
1.第一次运行原样(使用 cmets):然后结果将是 0(初始值)或 1(当线程 1 完成时)或 10(或线程完成)
2.Run with removing comment thread1.Join() : 结果应该总是大于 1。因为thread1.Join() 被触发并且线程 1 应该在得到总和之前完成.
3.删除所有评论运行:结果应始终为 11
【讨论】:
private static object locker = new object(); 然后lock (locker) { sum = sum + 1; }
Join 主要用于当您需要等待一个线程(或一组线程)终止后再继续执行您的代码时。
因此,当您需要从线程执行中收集结果时也特别有用。
根据下面的 Arafangion 评论,如果您在创建线程后需要执行一些清理/内务管理代码,那么加入线程也很重要。
【讨论】:
Join 将确保在执行下面的行之前执行上面的代码。
【讨论】:
另一个例子,假设你的工作线程从输入流中读取,而 read 方法可以永远运行,而你想以某种方式避免这种情况 - 通过使用另一个看门狗线程应用超时:
// worker thread
var worker = new Thread(() => {
Trace.WriteLine("Reading from stream");
// here is the critical area of thread, where the real stuff happens
// Sleep is just an example, simulating any real operation
Thread.Sleep(10000);
Trace.WriteLine("Reading finished");
}) { Name = "Worker" };
Trace.WriteLine("Starting worker thread...");
worker.Start();
// watchdog thread
ThreadPool.QueueUserWorkItem((o) => {
var timeOut = 5000;
if (!worker.Join(timeOut))
{
Trace.WriteLine("Killing worker thread after " + timeOut + " milliseconds!");
worker.Abort();
}
});
【讨论】:
在 devopsEMK 的帖子中在方法“Sample”中添加 300 毫秒的延迟和在“Sample2”中添加 400 毫秒的延迟会更容易理解。
通过这样做,您可以通过从“thread1.Join();”中删除注释来观察到这一点行,主线程等待“thread1”完成,并且只有在继续之后。
【讨论】: