2014-05-02 2 views
3

Я видел похожие вопросы, но никто, казалось, не ответил мне.Основные вопросы по заполнению

Я пытаюсь понять потоки вообще, но просто используя C#, чтобы исследовать их.

Так что у меня это в моем главном():

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) сразу после первого, тогда выполнение этого останавливает первый и запускает второй. Что именно здесь происходит? Является ли C# выполнением управления памятью и уничтожением первого потока, когда я выполняю объединение во втором потоке? Потому что я назначаю одну и ту же переменную? Почему бы им не играть параллельно?

Благодаря

ответ

3

Во-первых, нет никакого реального смысла в создании нового потока просто Join на него сразу же, в почти всех случаях. Вы могли бы просто выполнить все действия, которые вы сделали бы в исходном потоке; он будет делать то же самое, не тратя время на выполнение очень дорогостоящей работы по созданию, управлению и разрыву потока.

Что касается того, почему ваша программа продолжается, несмотря на Join, это потому, что ваши методы PlayMp3 и PlayWav являются асинхронными. Они начинают играют музыку, но эти методы не блокируются до тех пор, пока песня не будет выполнена; они возвращаются почти сразу. Поскольку они возвращаются, поток заканчивается почти сразу, поэтому ваш метод Join возвращает довольно много сразу. Если ваши потоки выполняли работу, которая на самом деле занимала значительное количество времени, тогда вы увидите Join, ожидая ее завершения.

Что касается того, почему последующие звонки в Play останавливают предыдущие песни, он не имеет ничего общего с приведенным здесь кодом. Похоже, что ваши методы PlayMp3 и PlayWav разработаны таким образом, что если их вызывают, когда еще играет песня, они остановят эти песни. Он не имеет никакого отношения к коду, который вы указали.

+0

Да имеет смысл. Я использую WMPlib.WindowsMediaPlayer, который, как я думаю, асинхронно воспроизводит его, и поток, который я создаю, существует только временно, чтобы отключить медиа-плеер, а затем завершается. Также вторая игра останавливает первую, потому что я использовал тот же объект медиаплеера. Если я создаю новый каждый раз, то он играет параллельно. Спасибо – shek

1

Когда поток вызывает Join(), он указывает, что он готов прекратить дальнейшую обработку по этой теме до тех пор, пока целевой поток не закончит работу. Обычно я использую Join(), когда пытаюсь закрыть все, чтобы вещи происходили упорядоченным образом.Я почти никогда не вызываю Join() из потока пользовательского интерфейса, потому что я не хочу, чтобы он прекратил обработку ввода пользователем.

Что делать PlayMp3 и PlayWav делать? Основываясь на вашем описании, я предполагаю, что они передают указанный файл медиа-плееру, а затем выходят. Таким образом, ваш основной поток запускает рабочий поток, чтобы передать файл в другую программу с собственной моделью потоковой обработки, а затем рабочий поток завершается. Как только это произойдет, основной поток продолжает выполнение, потому что поток, который он ожидал (через Join()), вышел из.

Попробуйте это. Поставьте рабочий поток спать в течение 10 секунд перед тем, как он выйдет. Вы должны увидеть паузу основного потока в течение 10 секунд, когда она вызывает Join().

+0

Да теперь имеет смысл. Моя PlayMp3 делает именно то, что вы догадались. И включение рабочего потока в режим сна блокирует мой основной поток. благодаря – shek

Смежные вопросы