2014-05-02 53 views
3

我看到了類似的問題,但似乎沒有人回答我的問題。基本線程問題

我想了解一般的線程,但只是使用C#來探索它們。

所以我有這個在我的主要():

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

和播放功能如下:

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。它表示加入阻止調用線程,直到當前線程終止。但是當我追蹤它時,它剛剛開始播放mp3,並且控制流也一直保持在主線程中。那麼它是什麼意思呢阻止了主線程,顯然不是這樣做的......

其次,如果我在第一個之後再添加sp.Play(path2),那麼執行該命令會停止第一個,然後開始第二個。到底發生了什麼?當我在第二個線程上執行Join時,C#是否正在執行內存管理並關閉第一個線程?因爲我分配給相同的變量?爲什麼它不能同時播放它們?

感謝

回答

3

首先,有一個在創造一個新的線程只是Join上它了,在幾乎所有情況下都沒有真正的點。你可能只是做一些你在原始線程中會做的動作;它會做同樣的事情,而不花時間來執行創建,管理和拆除線程的非常昂貴的工作。

至於爲什麼你的程序繼續運行,儘管Join,這是因爲你的PlayMp3PlayWav方法是異步的。他們開始播放音樂,但這些方法不會阻止,直到歌曲完成;他們幾乎立即返回。因爲他們回來了,線程幾乎馬上就完成了,所以你的Join方法幾乎立即返回。如果你的線程正在做的工作,實際上花了相當長的時間,那麼你會看到Join等待它完成。

至於爲什麼後續撥打Play停止以前的歌曲,它與這裏顯示的代碼沒有任何關係。看起來您的PlayMp3PlayWav方法的設計方式是,如果在另一首歌曲仍在播放時調用它們,則會停止播放這些歌曲。它與你所顯示的代碼無關。

+0

是有道理的。我正在使用WMPlib.WindowsMediaPlayer,我猜它是異步播放的,而我創建的線程只是臨時存在才能關閉媒體播放器,然後終止。第二個播放停止了第一個,因爲我使用的是同一個媒體播放器對象。如果我每次都創建一個新的,那麼它並行播放。謝謝 – shek

1

當線程調用Join()時,表示它願意在該線程上停止進一步處理,直到目標線程完成運行。當我試圖關閉一些事情以便事情有序地發生時,我通常會使用Join()。我幾乎從不從用戶界面線程調用Join(),因爲我不希望它停止處理用戶輸入。

PlayMp3PlayWav做什麼?根據您的描述,我的猜測是他們將指定的文件關閉到媒體播放器,然後退出。因此,您的主線程啓動一個工作線程將文件交給另一個具有自己的線程模型的程序,然後工作線程退出。一旦發生這種情況,主線程將繼續執行,因爲它正在等待的線程(通過Join())已退出

試試這個。工人線程在退出之前休眠10秒。當它調用Join()時,您應該看到主線程暫停10秒。

+0

現在是完美的。我的PlayMp3完全符合你的猜測。讓工作者線程進入休眠狀態確實阻塞了我的主線程。謝謝 – shek