System.Threading.Timer: Почему он ненавидит меня? - PullRequest
0 голосов
/ 06 февраля 2011

Я только начал возиться с 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 Ответ

2 голосов
/ 06 февраля 2011

Хочу отметить, что 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 несколько потоков, но если нет, существует вероятность, что весь обратный вызов должен быть вызван в пользовательском интерфейсе.

...