2

冒着听起来像个菜鸟的风险,我如何在 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。

4

2 回答 2

3

我在msdn论坛上得到了答案。有人给我留言,其中包含 codeplex ( nito.async ) 的链接。我使用 GenericSynchronizingObject 来完成工作。

于 2009-02-24T04:17:11.323 回答
0

你得到的错误代码是什么?我想它的一部分与 hwndCallback 参数有关,但是没有看到任何代码示例,很难说。

但是,您不需要在这里实现 ISynchronizeInvoke。如果要为回调传递窗口句柄,则可能必须调用它。在这种情况下,您需要在实现 ISynchronizeInvoke 的托管表示上调用 Invoke 方法。换句话说,您从中获得句柄的控件/表单。

于 2009-02-20T01:32:30.660 回答