09-08-2013 08:50 PM - edited 09-08-2013 08:51 PM
I am an experienced LabVIEW developer but a newbie c# .NET developer. When I want to keep my GUI responsive in LabVIEW, I use a simple producer/consumer pattern with two while loops. I have been looking into doing this with c#, and it seems like I need to use the system.threading collection. In general the power of this collection seems like massive overkill for what I need to do. Is there a step-by-step guide somewhere describing how to make a simple producer (GUI thread) consumer (instruments, robot, etc) two threaded program using c#?
09-09-2013 11:34 AM
Rather than managing threads directly, a simpler choice would be to use a Task
and an IProducerConsumerCollection<T>
like BlockingCollection<T>
.
In addition to the examples in the MSDN documentation, this walkthrough may also be useful.
09-09-2013 11:45 AM
This new collection for .NET 4.0 seems focused on performing advanced parallel tasks on shared data that requires thread safety. What I am trying to do is so simple it does not require this power. My test flow takes a while to finish testing a device. I need the GUI to remain responsive while the test flow is running. This way the operator can hit the "abort" button so that the tester will halt testing after finishing the current device.
09-09-2013 01:35 PM
I misunderstood what you needed from the LabVIEW example. For a simple "do one item of work" case, all you need is the Task
. If the "abort" button acts on your code rather than the device, you can use a cancellation token to check for an early exit. In pseudocode:
// In "begin" button handler, start task.
Task.Factory.StartNew( ( object state ) => {
var token = (CancellationToken)state;
// Do long-running work, perodically checking for "abort".
{
...
if( token.IsCancellationRequested ) {
// Cleanup...
token.ThrowIfCancellationRequested( );
}
}
}, cancellationSource.Token, cancellationSource.Token );
...
// In "abort" button handler, cancel task.
cancellationSource.Cancel( );
09-09-2013 01:41 PM
Hi Paul,
Thanks for your response. Clearly I have a brutal learning curve ahead of me to implement this in c#. Now I understand why LabVIEW is worth >$2500.
If I have limited time to study new programming libraries, would you recommend trying to learn this "task" based method, or the "background worker" method? I tried to follow a "background worker" tutorial but the example wouldn't work for me...
09-09-2013 02:32 PM
Both Task
and BackgroundWorker
handle operations separate from the UI thread, so for your one-item case either would be a workable option.
It sounds like you do not need any of the advanced options on Task
, so the simplest overload of Task.Factory.StartNew
will work. With BackgroundWorker
, there is an extra step to hook up the work event before starting the worker. Here's a simpler version of the pseudocode example (without cancellation):
// Task
Task.Factory.StartNew( delegate { DoWork( "task" ); } );
// Background Worker
var worker = new BackgroundWorker( );
worker.DoWork += delegate { DoWork( "background worker" ); };
worker.RunWorkerAsync( );
09-09-2013 03:15 PM
@joshxdr wrote:
Hi Paul,
Thanks for your response. Clearly I have a brutal learning curve ahead of me to implement this in c#. Now I understand why LabVIEW is worth >$2500.
very easy to understand Walkthrough: Multithreading with the BackgroundWorker Component (C# and Visual Basic) http://msdn.microsoft.com/en-us/library/ywkkz4s1%28v=vs.100%29.aspx
09-09-2013 05:34 PM
It turns out my problems with the BackgroundWorker tutorial was that I had not created the callbacks the way Visual Studio wanted me to. I needed to drop the compenent into the form, select the form, select the lightning bolt over the properties window, and then double click on the callbacks. This way VS knows to register the event with the callback. I was copying code from the example and this was leaving some things out. The example is working now and I think the BackgroundWorker will do the job for me. It is still tougher to do in C# than in LabVIEW...
09-10-2013 10:04 AM
In case anyone stumbles onto this thread with the same question, I have done some research on the difference between using Task and using BackgroundWorker. BackgroundWorker is an old component from .NET 2.0 that was designed specifically for newbies like me. You can drop it into your form and create callbacks using the same kinds of actions you would use for a graphical control. The functionality is very limited, and it is designed specifically for cases when you have a long running operation and you want to keep the GUI responsive. The Task/CancellationToken approach mentioned by Paul is part of a shiny new multithreading framework added in .NET 4.0. If you have aspirations to be a c# expert, you should follow Paul's advice and use the Task/CancellationToken approach. For me, the simplest and quickest way to solve my immediate problem is to use BackgroundWorker.
09-13-2013 03:05 AM
Hello...Really interesting thread. Under .NET 2.0, doing work on a background thread has become a lot easier, with the introduction of the BackgroundWorker class. You no longer have to worry about cross-threading exceptions and checking a control’s InvokeRequired property.
Thanks for sharing such a nice thread..