冒着听起来像个菜鸟的风险,我如何在 System.Timers.Timer 上实现 ISynchronizeInvoke?
我有一个调用 mciSendString 的类(没有 UI)。我有一个应该轮询当前状态的计时器。课堂上的所有调用都有效,但不是来自 timers elapsed 事件的调用。我已经追踪到它在不同的线程上,但我没有比这更进一步。我想我需要在与该类相同的线程上调用一个委托,但我还没有任何运气来完成它。
代码示例:
[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 调用(无论它是什么,播放、停止等),它会起作用,并且 Poll() 的结果是我所期望的。当计时器触发时,结果 (res) 是 263,即MCIERR_INVALID_DEVICE_NAME
. 失败调用的 threadID 与成功调用的不同,这就是为什么我认为我需要使用 ISynchronizeInvoke。