views:

65

answers:

2

I am using Visual C# .Net via Visual Studio 2008 Express and I am launching a thread from a forms applications to wait on incoming data in a loop. So, each loop waits till data is available, then gets the data, and starts again waiting.

The main reason why I'm waiting for my data in a separate thread is so my form will still allow interaction while the other sits there waiting for data.

For whatever reason, my form will lock while my other thread is waiting.

Unfortunately, I am forced to use a proprietary function to acquire my data. Processing will literally stop at that function till data is returned by it (which waits on hardware inputs). So, a user can click in vain on menu options with no effect, till the child thread returns data and all the clicked menu options will quickly change status and lock up again.

So, my question is:
Why is my child thread holding up my form? Isn't is supposed to be independent? What can I do to force my form to continue to function if that child thread is waiting on something?

I am currently making my thread like this:

ControlThread = new Thread(new ThreadStart(Run));
ControlThread.Start();

Where my Run function is something like this:

public void Run()
{
    while (!StopEventHandle.WaitOne(0, true))
    {
        int data = WaitForData();
        invoke(DelegatedResults);
    }
}

Where DelegatedResults is a function on my form that updates some textboxes using the data that came in.

A: 

You should Sleep that Thread at least by 1.

SHORT ANSWER::

this.Invoke((ThreadStart)delegate()
{
    textBox1.Text = "Yahoo";
});

LONG ANSWER::

using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Thread thread;
        bool finishingThread, finished;

        public Form1()
        {
            InitializeComponent();
            finishingThread = false;
            finished = false;
            thread = new Thread(Run);
            thread.Start();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            finishingThread = true;
            if(!finished) e.Cancel = true;
            base.OnClosing(e);
        }

        private void Run()
        {
            while(!this.Visible);
            while(this.Visible && !finishingThread)
            {
                this.Invoke((ThreadStart)delegate()
                {
                    textBox1.Text = "Yahoo";
                });
                Thread.Sleep(100);
            }
            finished = true;
            this.Invoke((ThreadStart)delegate()
            {
                this.Close();
            });
        }
    }
}
zezba9000
My Run thread does have a sleep in it somewhere, plus it does more than just wait on that one function to return. In essence, the main form does update, but only when it gets past the function.
Gorchestopher H
+1  A: 

I am forced to use a proprietary function to acquire my data

You didn't say much about that function. Your problem suggests that it was implemented as a COM server, pretty common. COM takes care of the threading requirements for the COM server. Such a server indicates in the registry with the ThreadingModel registry key what kind of threading it supports. A very common setting is "Apartment", also the default when the key is missing.

That setting indicates that the server doesn't support threading. It needs a Single Threaded Apartment (STA). COM takes care of that and it automatically marshals any call made on the server to an STA thread. Your UI thread. Which thus goes dead as a doornail until the call completes.

There ought to be something about this in the documentation for the library. Contacting the vendor for support would be a good idea as well. If you can't get help then the first thing you could try is initializing the server on the worker thread instead of your UI thread. That would solve the problem if the ThreadModel is "Both". If that doesn't help then you'll need to create your own STA thread. Call Thread.SetApartmentState() before starting the thread, start your own message loop with Application.Run() in the thread. You might be able to skip the loop but it is normally required.

Hans Passant
It is very likely that the function I am using to grab my data is set up to work in the most inconvenient way possible, documentation is very limited and comes out of an other continent. Having said that, I will likely need to defer to the STA thread suggestion. I'm very much a threading newbie. What do you mean by "start your own message loop"?
Gorchestopher H
Link: http://stackoverflow.com/questions/1995527/how-might-i-create-and-use-a-webbrowser-control-on-a-worker-thread/1995667#1995667
Hans Passant
A bit of additional info from the function I'm using:It's from a dotNet library, but it accesses other libraries that may or may not have COM components.What this function does is wait for a buffer to fill, then grab the data from the buffer, then tell the buffer to begin filling again.If the buffer isn't full when the function is called, it waits. There is no way to check the buffer status.
Gorchestopher H
Up this solution. Hans is the threadmaster.
Gorchestopher H