C # ISynchronizeInvoke Вопрос - PullRequest
       16

C # ISynchronizeInvoke Вопрос

2 голосов
/ 20 февраля 2009

Как выглядит 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.

Ответы [ 2 ]

3 голосов
/ 24 февраля 2009

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

0 голосов
/ 20 февраля 2009

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

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

...