Click here to Skip to main content
15,868,004 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
I have a long running task which performs a list of diagnostic tests on a remote device via Bluetooth. The test starts on a button click.
I have used a single thread[in MainForm] to iterate through a collection of test objects performing the below synchronously:
1. update UI for each test [in MainForm].
2. send test command to the device [handled by a separate class BTest.cs]

A timer in BTest.cs starts calculating test duration as soon as command is sent.

If test executed successfully, BTest.cs raised an event. This is captured in MainForm and test results are updated to UI.

Current implemention using single thread and invoke method for UI....freezes UI until thread completes its task.

Any alternate solution that does not freeze UI is much appreciated. Thanks in advance.
Posted

Long running tasks are done using threads, not timers. The only one little problem with having some extra thread performing such a long running task under the UI is that you cannot directly operate UI from that thread. This problem is solved using UI thread invocation mechanism.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

Now, it's most convenient to create a permanent thread and throttle it by using a event wait handle. Also, it is very convenient to encapsulate all that and also all synchronization and invocation mechanisms in a thread wrapper. This way, the thread can be reused as tasks are coming up. Please see my past answers:
Making Code Thread Safe[^],
Running exactly one job/thread/process in webservice that will never get terminated (asp.net)[^],
pause running thread[^],
ManualResetEvent and AutoResetEvent in Thread[^].

On the thread wrappers, see also:
How to pass ref parameter to the thread[^],
Change parameters of thread (producer) after it is started[^],
MultiThreading in C#[^].

Also, you can use a blocking queue for pushing some tasks to the thread wrapper (then the even thread handler is not needed, it is encapsulated in the queue, which can be a queue of delegate instances representing those tasks directly). This is explained in my article: Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

With .NET v.4 and later, you can use faster blocking queue already implemented in .NET FCL: http://msdn.microsoft.com/en-us/library/dd267312%28v=vs.110%29.aspx[^].

—SA
 
Share this answer
 
Comments
CPallini 6-May-14 16:56pm    
5.
Sergey Alexandrovich Kryukov 6-May-14 17:13pm    
Thank you, Carlo.
—SA
In Windows OS the UI refreshes when WM_PAINT message is sent to application. But messages in message queue has a priority - WM_PAINT has the lowest, so it will wait until have other messages...
You better move to multi-threaded application and learn how to update UI between threads...
You may start here: http://msdn.microsoft.com/en-us/magazine/cc300429.aspx[^].
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 6-May-14 15:46pm    
I don't want to down-vote this explanation about WM_PAINT, because this aspect is very delicate. But better don't provide such explanation, it is somewhat misleading.

But things are more complex than you try to explain. The main thing is not priority. This message is propagated and handled in a special way, not related to the message queue and the mechanism is not a priority-based. The idea is: invalidation request generally come with different areas, subsets of the client areas (either rectangles or regions), they can be explicit calls, or come from unmasking the window by showing areas covered by other windows on top of this one on z-order. The message propagation/handling for WM_PAIN is designed to minimize redundant redrawing. App pending invalidated subsets, before redrawing, are ORed together (disjunction is performed), and the the united area is being redrawing. This is implemented by using set-theory operations on the region available in Win32 API...

—SA
Kornfeld Eliyahu Peter 6-May-14 15:57pm    
I know about how multiple WM_PAINT messages are combined to reduce painting, but that is done only AFTER other messages - with higher priority - have been processed. While you are in a single threaded application that runs other operations WM_PAINT will sit at the bottom of the queue as long as there are other messages. I made it more simplified for OP because my point was that he have to move to multi-threaded application - one for computation and one for UI, than synchronize between the two...
Sergey Alexandrovich Kryukov 6-May-14 16:00pm    
Very good, but then it's better not to oversimplify the explanation, to avoid confusing the readers... The term "priority" actually means something different, despite of the similarity. It's not literally the priority (re-ordering the queue using some criteria)...
—SA
Kornfeld Eliyahu Peter 6-May-14 16:03pm    
You right - in fact there are different queues for different kind of messages, which is not priority in the common way ...
Sergey Alexandrovich Kryukov 6-May-14 16:13pm    
Great, we came to understanding of the matter...
Cheers,
—SA
Thank you all. I used manual reset event to wait for notification from each test. Now my app works.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900