C# ISynchronizeInvoke Вопрос

Рискуя показаться полным нубом, как реализовать 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.


person Krakerjak    schedule 20.02.2009    source источник


Ответы (2)


Я получил ответ на форуме msdn. Кто-то оставил мне сообщение со ссылкой на codeplex (nito.async). Я использовал GenericSynchronizingObject, чтобы выполнить работу.

person Krakerjak    schedule 24.02.2009

Какой код ошибки вы получаете? Я предполагаю, что часть этого связана с параметром hwndCallback, но, не видя примеров кода, трудно сказать.

Однако здесь вам не нужно реализовывать ISynchronizeInvoke. Возможно, вам придется вызвать его, если вы передаете дескриптор окна для обратного вызова. В этом случае вам потребуется вызвать метод Invoke для управляемого представления, реализующего ISynchronizeInvoke. Другими словами, элемент управления/форма, из которой вы получили дескриптор.

person casperOne    schedule 20.02.2009