2011-02-06 3 views
0

Я просто начал возиться с C# /. NET/mono и прочее, и я пытаюсь создать простой плеер песен. Для этого я использую winmm.dll (не нашел простого кросс-платформенного решения). Проблема заключается в следующем: мне нужно обновить трек-панель вместе с воспроизведением песни. У меня есть две функции: Player.GetLength и Player.GetCurrentPosition, которые возвращают время в миллисекундах. Если я назову их «нормально», все будет в порядке. Но мне нужно, чтобы вызвать их в таймере, как это:System.Threading.Timer: Почему он меня ненавидит?

new System.Threading.Timer((state) => 
{ 
    length = Player.GetLength(); 
    pos = Player.GetCurrentPosition(); 
    trackBar1.Value = (pos/length) * 100; 
}, null, 0, 100);  

Это GetLength и GetCurrentPosition похож:

public static int GetLength() 
{ 
    StringBuilder s = new StringBuilder(128); 
    mciSendString("status Song length", s, s.Capacity, IntPtr.Zero); 
    return int.Parse(s.ToString()); 
} 

Проблема:, когда одна из этих двух функций вызывается, программа просто останавливается, без предупреждения или исключения. Примечание: Я использую .NET

Так мне было интересно, если вы можете объяснить мне, где я получил это неправильно :)

ответ

2

Одна вещь, которую я бы отметить, что System.Threading.Timer выстреливает это обратный вызов в своей собственной нити. Так как вы взаимодействуете с пользовательским интерфейсом, вы либо хотите использовать System.Windows.Forms.Timer (в качестве компонента на форме) или вызвать обратно в пользовательский интерфейс, следующим образом:

new System.Threading.Timer((state) => 
{ 
    length = Player.GetLength(); 
    pos = Player.GetCurrentPosition(); 
    trackBar1.Invoke(new Action(()=>trackBar1.Value = (pos/length) * 100)); 
}, null, 0, 100); 

Кроме того, я Я не уверен, что класс Player поддерживает/переносит несколько потоков, но если нет, есть вероятность, что весь обратный вызов должен быть вызван в пользовательский интерфейс.

+0

Это работает, но я также хотел бы знать _why_. Не могли бы вы объяснить мне, что происходит? –

+0

В .NET (как и во многих других библиотеках пользовательского интерфейса на многих платформах) элементы управления пользовательского интерфейса не предназначены для доступа из нескольких потоков. Это позволяет им работать быстрее, потому что им не нужно беспокоиться о синхронизации данных. В вашем случае .NET на самом деле бросает исключение, жалуясь на то, что вы пытаетесь получить доступ к пользовательскому интерфейсу из фонового потока, но поскольку он находится в фоновом потоке, вы не видите, что генерируемое исключение. –

+0

Итак, я думаю, что единственный способ взаимодействовать с ними при использовании потоков - это '.Invoke', правильно? –

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

  • Нет связанных вопросов^_^