冒着听起来像总菜鸟的风险,如何在System.Timers.Timer上实现ISynchronizeInvoke?
我有一个类(没有UI)调用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调用(无论它是什么,播放,停止等),它的工作原理和Poll()的结果是我所期望的。当计时器触发时,结果(res)为263,即MCIERR_INVALID_DEVICE_NAME
。失败的调用中的threadID与成功的调用不同,这就是为什么我认为我需要使用ISynchronizeInvoke。
答案 0 :(得分:3)
我在msdn论坛上得到了答复。有人留给我一条带有codeplex(nito.async)链接的消息。我使用GenericSynchronizingObject来完成工作。
答案 1 :(得分:0)
您获得的错误代码是什么?我想它的一部分与hwndCallback参数有关,但是没有看到任何代码示例,很难说。
但是,您不需要在此处实现ISynchronizeInvoke。如果要传递回调的窗口句柄,则可能必须调用它。在这种情况下,您需要在实现ISynchronizeInvoke的托管表示上调用Invoke方法。换句话说,你得到句柄的控件/表格。