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