Solved

Main Thread calls a new Thread. How Do I Synchronise when new thread is finished?

Posted on 2009-06-29
9
256 Views
Last Modified: 2012-05-07
Im developing a windows application (not Internet based)  using Visual Studio 2008 and Visual C#.

The application basically reads the output from some  hardware then processes the information and draws graphs etc. The part where it reads infomation from the hardware can take up to ten minutes and basically locks up the computer. I want to have this bit in a separate thread so it can be aborted if necessary and so the computer can do other things.

When the user clicks a button the following code is executed on the Main Thread.
 
'threadTask' is the function that reads from the hardware and is the executed from the new thread.

  Thread trd = new Thread(new ThreadStart(this.threadTask));
   trd.IsBackground = true;
   trd.Start();

Now when this function finishes I want this thread to basically end and another function (that processes  the information) to start executing. This function (lets call it Process) should in the Main thread.

How do I synchronise so that the function Process on the Main thread is executed when the thread I created to read from the hardware (the function threadTask) is finished?

Note all the data is stored in class variables so I dont need to send data as function arguments etc.
0
Comment
Question by:rangers99
  • 4
  • 3
  • 2
9 Comments
 
LVL 8

Expert Comment

by:InternalStatic
ID: 24737547
You could have a central locking sync object. Take this for example. The "lock" statement attempts to acquire an exclusive "lock" on an object (make sure one exists, though--null should throw an exception). If a lock has already been acquired on an object, it will wait until unlocked.
You could also use the Monitor class for more "finite" control over your thread sync'ing. I'll provide a link for that, as it is not really imperative.
http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx
Hope it helps,
Nate

// Inside main class

private Object sync = new Object();
 

// "Main" thread--method that initiates everything

private void MainWorkHandler()

{

     Thread t = new Thread(this.threadTask);

     t.IsBackground = true;

     t.Start();

     lock(sync)

     {

          // Draw your grahps and such; the other thread is done

     }

}

private void threadTask()

{

     lock(sync)

     {

          // Get the information from the hardware

     }

}

Open in new window

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24737957
@InternalStatic...wouldn't that be counter-productive?...

The author states:

    "The part where it reads infomation from the hardware can take up to ten minutes..."

So threadTask() will lock "sync" and then start performing its task...which could take "up to ten minutes", and keep "sync" locked until it completes.

Meanwhile, the main thread will also attempt to lock "sync", but will fail because threadTask() already has it.  This will result in the main thread BLOCKING until "sync" has been released:
http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.80).aspx

    "If another thread attempts to enter a locked code, it will wait, block, until the object is released."

End result will be a completely unresponsive GUI.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 100 total points
ID: 24738114
To answer this question:

    "How do I synchronise so that the function Process on the Main thread is executed when the thread I created to read from the hardware (the function threadTask) is finished?"

I would think a simple "this.Invoke()" would do the trick:
    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }
 

        private delegate void ProcessDataDelegate();
 

        private void button1_Click(object sender, EventArgs e)

        {

            Thread trd = new Thread(new ThreadStart(this.threadTask));

            trd.IsBackground = true;

            trd.Start();

        }
 

        private void threadTask()

        {

            // ...simulated processing...

            System.Threading.Thread.Sleep(Convert.ToInt32(TimeSpan.FromSeconds(10).TotalMilliseconds));
 

            this.Invoke(new ProcessDataDelegate(ProcessData));

        }
 

        private void ProcessData()

        {

            // ...this is now back on the main UI thread...
 

            this.label1.Text = "Processed data...";

        }

    }

Open in new window

0
 
LVL 8

Expert Comment

by:InternalStatic
ID: 24739939
Idle_Mind: I'm pretty sure what he's saying is he needs the information from the hardware BEFORE the graphing and such can be done. From what I read from the question, I see nothing about illegal thread crossing exceptions or the like. He just wants the task to be done on a thread other than the window's message loop, in case he wishes to cancel the operation.
Author, is this correct, or am I missing the point?
Nate
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 8

Expert Comment

by:InternalStatic
ID: 24739978
I'm assuming that the data processing part is not time-consuming, which is why I put it on the same thread as the message loop. If this is not accurate, you should use this.Invoke for the data processing.
Hope this helps,
Nate
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24740098
I could be interpreting wrong too...can't ignore that possibility!   =)

I'll restate my concern differently though as I think you've missed an important detail.
 
The author is starting the secondary thread from a BUTTON click:

    "When the user clicks a button the following code is executed on the Main Thread."

...and your code has:

     // inside the button click handler
     ... start up secondary thread ...
     lock(sync)
     {
          // Draw your grahps and such; the other thread is done
     }

When the main UI hits "lock(sync)" it is going to BLOCK until threadTask() completes (which could take up to ten minutes).  This is because the "sync" object has already been locked by the secondary thread.

So what you've essentially done is created a completely locked up main thread.  It won't respond to user interaction and will not paint correctly resulting in the commonly seen "white out" symptom.

The approach you've given is a perfectly valid one for synchronizing threads...it's just not the best choice when one of those threads is the main UI thread!  ;)

A key difference between mine and yours is that you've attempted to keep the "flow" of the code INSIDE the same method that started the secondary thread while I have seperated it out so that a DIFFERENT method is executed once the secondary thread has completed.
0
 
LVL 8

Assisted Solution

by:InternalStatic
InternalStatic earned 25 total points
ID: 24740571
Hmm, yeah I didn't think about it that way--I always assume more complexity than is necessarily present ;)
Idle_Mind is right, you should probably have the other lock statement lock on a thread other than the UI thread--otherwise, re-paint messages and such won't be sent to the window. You can edit the code as follows to "free up" the UI thread, while still maintaining the sync.
There are obviously a ton of ways to do this, so if any of these ways don't work, we'll need some more details.
Hope it helps, and thanks Idle_Mind,
Nate

// Inside main class

private Object sync = new Object();

 

// "Main" thread--method that initiates everything

private void MainWorkHandler()

{

     Thread t = new Thread(this.threadTask);

     t.IsBackground = true;

     t.Start();

     new Thread(ProcessData).Start();

}

private void threadTask()

{

     lock(sync)

     {

          // Get the information from the hardware

     }

}

private void ProcessData(Object ignore)

{

     lock(sync)

     {

          // Process your data in whatever way you wish

     }

}

Open in new window

0
 

Author Comment

by:rangers99
ID: 24743398
Nate said:

"Idle_Mind: I'm pretty sure what he's saying is he needs the information from the hardware BEFORE the graphing and such can be done. From what I read from the question, I see nothing about illegal thread crossing exceptions or the like. He just wants the task to be done on a thread other than the window's message loop, in case he wishes to cancel the operation.

Author, is this correct, or am I missing the point?"


Yes Nate that correct.

Thanks for all the replies. Im going to read through them all now!
0
 

Author Closing Comment

by:rangers99
ID: 31597967
IdleMind
I tried out the sample code you posted and it does exactly what I require. Thanks.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now