Темы UI и кошмары - PullRequest
       27

Темы UI и кошмары

0 голосов
/ 06 июня 2011

У меня есть класс, который обрабатывает некоторые действия в реальном времени в потоке, который он запускает. В этом приложении есть и другие игры, так как оно очень сложное. Когда начинается это действие rt, мне нужно открыть окно и закрыть его, когда оно будет завершено. Звучит просто.

Есть события, к которым я подключаюсь, когда это действие начинается и останавливается. В этих обработчиках событий я размещаю код:

        private void Voice_SpeakStarted(object sender, TMSpeakStartedEventArgs e)
    {

        InfoWindow = new Form();
        InfoWindow.Show();
    }

    /// <summary>
    /// this is the event handler speaking stops
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Voice_SpeakCompleted(object sender, TMSpeakCompletedEventArgs e)
    {
        if (InfoWindow.InvokeRequired)
        {
            InfoWindow.Invoke(new Action(() =>
            {
                InfoWindow.Close();
            }));

            InfoWindow.Hide();
        }
    }

Иногда я получаю сообщение об ошибке, что поток завершен. (Произошла ошибка при вызове метода. Целевой поток больше не существует.)

Кажется, у меня всегда есть окно, чтобы показать. Я не могу заставить окно закрыться.

Я также вижу, что иногда сам обработчик не вызывается.

Мне нужна плохая помощь. Я могу опубликовать больше кода, если это будет полезно.

Отредактировано - добавлено больше кода Так я начинаю занятия

        public void start()
    {
        //It's already alive, nothing to do
        if (alive) return;

        //Make sure this is the only place where alive is set to true
        alive = true;

        Voice.SpeakCompleted += new Speech.TMSpeakCompletedDelegate(Voice_SpeakCompleted);
        Voice.SpeakStarted += new Speech.TMSpeakStartedDelegate(Voice_SpeakStarted);


        dispatch = new Thread(new ThreadStart(ProcessSayList));
        dispatch.Start();
    }

Конструктор класса

    public AnimationControl(dynamic parent)
    {
        Parent = parent;
        Voice = new Speech();

        q = Queue.Synchronized(new Queue(1000));
        start();
    }

Ответы [ 3 ]

1 голос
/ 19 июня 2011

Проверьте мой ответ здесь для получения некоторой информации о прерванной ошибке потока и потоке пользовательского интерфейса в целом: понимание исключений InvalidAsynchronousStateException

1 голос
/ 07 июня 2011

Вы должны действительно специализировать свой поток и прекратить вызывать код, управляемый другим потоком, из любого потока. Используйте очереди сообщений для передачи действий в ваш поток. Это самый безопасный способ многопоточности.

Пример в псевдокоде:

Thread1
{
  while (1)
  {
    read my last message in my queue;
    do something according to this message like:
    openwindow();
    or closewindow();
  }
}

Thread2
{
  My life is short, I just need to post a message to thread1
}


Thread3
{
  etc.
}

В каждой системе есть готовые структуры для таких вещей. И благодаря этому будет гораздо легче понять, что происходит в случае подобной проблемы. Конечно, если вы не позаботитесь, ваша многопоточная программа может стать абсолютно линейной; цель состоит в том, чтобы некоторые части действий могли выполняться параллельно и не создавать цепочку потоков, ожидающих друг друга, один за другим:)

0 голосов
/ 07 июня 2011

Ну, во-первых, вы вызываете Hide в своем окне не в том потоке, даже если InvokeRequired возвращает true.

Я также могу предположить, что вы создаете свой экземпляр Voice в новом потоке и возвращаетесь, когда получаете сообщение "close", что иногда приводит к уничтожению потока, через который вы пытаетесь перенаправить сообщения Windows. Подумайте о том, чтобы удерживать нить, пока ваше окно не закроется.

И да, вы должны опубликовать больше кода, нет ни одной строки кода, показывающей, как вы создаете / распоряжаетесь этим потоком.

...