Click here to Skip to main content
15,896,118 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a Windows Form with a PictureBox. I want to use and Timer and Task in the background to check for Image updates and refresh if new Image is available.

I am getting confused using Task and whether I need to use await and async.
I don't want the UI to be blocked while running Task.

Looking here: http://dotnetcodr.com/2014/01/01/5-ways-to-start-a-task-in-net-c/

he uses async method and await but I found only way to call an async method is to use await. But then that method which is calling it should call it using await and so on.
But I can't make all methods async?

Also I thought by using Tasks and async I should not have to wait?
In the past I used backgroundWorker and did not wait?!

C#
void timerRefreshImage_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Task t = new Task(() => RefreshImage());
            t.Start();
        }

        private void RefreshImage()
        {
            try
            {
                Task.Run(()=>GetCameraImage(true));
            }
            catch (Exception t)
            {
                throw t;
            }

        }


What would be the best approach(es) to update the images?
Posted
Comments
Sergey Alexandrovich Kryukov 9-Feb-15 20:56pm    
It all depends on what GetCameraImage does, periodically or not, does anything push notification or not.
One note: you catch and throw does nothing, only wastes some resources. It is fully equivalent to not handling exceptions at all (would be the best, the idea of handling exceptions locally is wrong).
—SA

1 solution

Please see my comment to the question. You are trying to make things more complex than they have to be, especially the use of the timer. First of all, the whole idea of periodic polling of something is pretty bad wasteful. Please see my past answer for some explanations: Application 'dashboard' for website accounts[^].

Now, if I still had to do this polling, I would do the simple thing: create a permanently working thread doing acquisition in the loop, with some delay (System.Thread.Sleep(delay)) in the loop. Now, the problem is sending the acquired image to the UI. Not actually a problem. 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).

In your case, I would use Invoke, not BeginInvoke. Why? This would throttle the thread, so it would not do unwanted image acquisition when the UI is not ready to accept it. Actually, this consideration is the key to understanding why the timer is really bad (in most cases, actually): did you ever try to take into account the cases when the handling of a timer event is not yet complete when new event is invoked? It's always better to stay away from such things.

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[^].

—SA
 
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