Рискуя показаться полным нубом, как реализовать ISynchronizeInvoke в System.Timers.Timer?
У меня есть класс (без пользовательского интерфейса), который вызывает mciSendString. У меня есть таймер, который должен опрашивать текущий статус. Все вызовы из класса работают, но не те, которые исходят от события, прошедшего с таймерами. Я проследил, чтобы это было в другой ветке, но я не продвинулся дальше этого. Я думаю, мне нужно вызвать делегата в том же потоке, что и класс, но мне пока не повезло.
Пример кода:
[DllImport("winmm.dll")]
private static extern Int32 mciSendString(string command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
public cPlayer()
{
tmrPoll = new System.Timers.Timer(1000);
tmrPoll.Enabled = false;
tmrPoll.Elapsed += new ElapsedEventHandler(tmrPoll_tick);
}
public void tmrPoll_tick(object source, ElapsedEventArgs e)
{
Poll();
}
private void Poll()
{
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
tmrPoll.Stop();
int res = 0;
res = mciSendString("status MediaFile position", _sbBuffer, _sbBuffer.Capacity, IntPtr.Zero);
if (res == 0) _position = int.Parse(_sbBuffer.ToString());
if (res == 0)
{
Console.WriteLine("Position = " + _sbBuffer.ToString());
} else {
Console.WriteLine("Failed: Error " + res.ToString());
}
res = mciSendString("status MediaFile length", _sbBuffer, _sbBuffer.Capacity, IntPtr.Zero);
if (res == 0) Console.WriteLine("Length = " + _sbBuffer.ToString());
if (res == 0) _length = int.Parse(_sbBuffer.ToString());
res = mciSendString("status MediaFile mode", _sbBuffer, _sbBuffer.Capacity, IntPtr.Zero);
if (res == 0) Console.WriteLine("Mode = " + _sbBuffer.ToString());
}
private void SendCommand(string cmd)
{
mciSendString(cmd, null, 0, IntPtr.Zero);
Poll();
}
Для пояснения, если я позвоню из SendCommand (что бы это ни было, Play, Stop и т. д.), это сработает, и результат Poll() будет таким, как я ожидал. Когда таймер срабатывает, результат (res) равен 263, что равно MCIERR_INVALID_DEVICE_NAME
. Идентификатор потока при неудачном вызове отличается от успешного, поэтому я решил, что мне нужно использовать ISynchronizeInvoke.