开发者

Threads UI and nightmares

开发者 https://www.devze.com 2023-03-11 16:15 出处:网络
I have a class that handles some realtime action in a thread that it starts.There are other theads in play in this application as it is very complex.When This rt action starts i need to pop up a windo

I have a class that handles some realtime action in a thread that it starts. There are other theads in play in this application as it is very complex. When This rt action starts i need to pop up a window and close it when it is done. Sounds easy.

There are events that I hook to when this action starts and stops. In those event handlers I place the code:

        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();
        }
    }

There are times I get an error that the thread has terminated. (An error occurred invoking the method. The destination thread no lon开发者_开发问答ger exists.)

I always seem to get the window to show. I can not seem to get the window to close.

I also see that sometime the handler themselves do not get called.

I need help bad. I can post more code if it would be helpful.

Edited - added more code This is how I start the class

        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();
    }

The constructor of the class is

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

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


You should really specialize your thread and stop calling code managed by other thread form any thread. Use message queues to communicate actions to your thread. This is the safest way to do multi-threading.

Example in pseudo-code:

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.
}

There are ready-to-use structures for such a thing on every system. And by doing so, it will be much more easy to understand what's happening in case of problem like that. Of course, if you don't take care, your threaded program can become absolutely linear; the goal is to make sure some parts of actions can be made in parallel and do not create a chain of threads waiting each other, one by one :)


Check my answer here for some information on the thread terminated error, and UI threading in general: understanding InvalidAsynchronousStateException occurrences


Well for one thing you're calling Hide on your window on the wrong thread even if InvokeRequired returns true.

I can also guess that you're creating your Voice instance on a new thread and returning when you get a "close" message, thus sometimes killing the thread you're trying to route windows messages through. Consider holding on to the thread until your window is actually closed.

And yes, you should post more code, there isn't a single line of code that shows how you create/dispose of that thread.

0

精彩评论

暂无评论...
验证码 换一张
取 消