基本的线程问题

时间:2014-05-02 13:56:29

标签: c# .net multithreading

我看到了类似的问题,但似乎没有人回答我的问题。

我试图理解一般的线程,但只是使用C#来探索它们。

所以我在main()中有这个:

var sp = new SongPlayer();
sp.Play(path);

Play功能如下所示:

public void Play(string path)
{
    if (path.EndsWith("mp3"))
        songThread = new System.Threading.Thread(() => PlayMp3(path));
    else if (path.EndsWith("wav"))
        songThread = new System.Threading.Thread(() => PlayWav(path));

    songThread.Start();
    songThread.Join();
}

(songThread是System.Threading.Thread类型)

有人可以向我解释一下幕后究竟发生了什么吗?

如果我添加一个断点并逐步执行,当我执行songThread.Join()时,mp3开始播放。我猜测它在调用Start()后没有开始播放,因为控制流仍然在主线程内。如果我没有Join语句,而是执行Thread.Sleep(),那么子线程也会执行,但我的问题是关于Join。它表示Join 阻塞调用线程,直到当前线程终止。但是当我追踪它时,只是开始播放mp3并且控制流也继续在主线程中进行。那么它阻止主线程意味着什么呢,它显然没有这样做......

其次,如果我在第一个之后添加另一个sp.Play(path2),那么执行它会停止第一个并启动第二个{{1}}。到底发生了什么?当我在第二个线程上执行Join时,C#正在进行内存管理并查出第一个线程吗?因为我分配给同一个变量?为什么它不能并行播放?

由于

2 个答案:

答案 0 :(得分:3)

首先,在几乎所有情况下,立即在Join上创建一个新线程没有任何意义。你也可以做你在原始线程中所做的任何动作;如果不花时间执行创建,管理和拆除线程这项非常昂贵的工作,它也会做同样的事情。

至于为什么你的程序会继续Join,这是因为你的PlayMp3PlayWav方法是异步的。他们开始播放音乐,但这些方法在歌曲完成之前不会阻止;他们几乎立即回来。因为它们返回,所以线程立即完成,因此您的Join方法几乎立即返回。如果您的线程正在进行实际花费相当长时间的工作,那么您会看到Join等待它完成。

至于为什么后续调用Play会停止之前的歌曲,它与此处显示的代码完全无关。看来您的PlayMp3PlayWav方法的设计使得如果在另一首歌还在播放时调用它们,则会停止播放这些歌曲。它与您展示的代码无关。

答案 1 :(得分:1)

当一个线程调用Join()时,它表示它愿意停止在该线程上进一步处理,直到目标线程完成运行。当我试图关闭事物时,我通常使用Join(),以便事情有序地发生。我几乎从不从用户界面线程调用Join(),因为我不希望它停止处理用户输入。

PlayMp3PlayWav做了什么?根据您的描述,我的猜测是他们将指定的文件传递给媒体播放器,然后退出。因此,您的主线程启动一个工作线程将文件移交给另一个具有自己的线程模型的程序,然后工作线程退出。一旦发生这种情况,主线程继续执行,因为正在等待的线程(通过Join())退出

试试这个。在工作线程退出之前将其置于睡眠状态10秒钟。当调用Join()时,您应该看到主线程暂停10秒钟。