Wait task on x amount of time and progress report

I need a better design for a sleeping task than Thread.Sleep, I use the Task class.

In my wpf application, I run a task, this task launches another pair of tasks, each of which performs the first login to the system and to the Internet website, after entering the system they need to wait a couple of seconds and tell the user when they will start next and this my problem is because with Thread.Sleep I cannot report progress.

There are more functions than a login, it's about 5-6, they all request an Internet resource, and between them there should be a timeout with the remaining send do gui time report, this 5-6 function is in one task, but there can be many tasks .

I need the task to wait, but it also allows me to send updates in the remaining time to go to the GUI.

Do you have any ideas on this problem, how to do it better, maybe you already have some design patterns for such a problem?

I also heard that using Thread.Sleep is bad design practice.

EDIT: Nobody knows? What is waiting with some kind of standalone timer with a thread, like waithandle, autoresetevent, anyone?

+8
wait wpf task progress
source share
4 answers

Forget about using Thread.Sleep. Instead, run the task in the background thread and use WaitHandle with AutoResetEvent. (Links: WaitHandle / WaitOne / AutoReset )

Your background thread can send updates to the user interface with asynchronous delegates, but the calling thread will wait for it until nothing happens:

1) Your thread reports that it has completed its task using yourwaithandle.Set ();

or

2) wait wait timeouts (the timeout value is set as a parameter for the WaitOne () method).

+1
source share

The solution is to treat it as an asynchronous callback, rather than a synchronous wait. If you are using Async CTP, the correct way would be:

async item => { await Task.Delay(1000); Process(item); }

It also seems like an ideal use case for DataFlow or Rx.

Using reactive extensions:

 static void Track(int timeout, int frequency, string item) { Observable.Interval(TimeSpan.FromSeconds(frequency)) //produces 0, 1, 2.. with the interval .Do(i => Console.WriteLine("Working on {0}", item)) // work on item .TakeUntil(Observable.Timer(TimeSpan.FromSeconds(timeout))) //stop once the timer publishes a value .Subscribe ( i => Console.WriteLine("Reporting {0}%", ((double)(i + 1) / timeout * 100)), // the interval reaches OnNext e => Console.WriteLine("Error!"), // error occured () => Console.WriteLine("Completed") // observable completed ); } 

When called using Track(timeout: 5, frequency: 1, item: "http://example.com/?") output is:

 Working on http://example.com/? Reporting 20% Working on http://example.com/? Reporting 40% Working on http://example.com/? Reporting 60% Working on http://example.com/? Reporting 80% Completed 
+6
source share

Instead of having one task to perform all these half-dozen functions (login, etc.), each function performs a separate task. Then you can create a priority queue ordered by time. When you want to run one of these meta tasks, you put your first function in the queue along with status data (i.e. URL, user ID, password, etc.).

As each function completes, it pauses the next function. Therefore, if the first two functions are login and get_data, you will have:

 queue login with state data to execute at DateTime.Now When login is finished, it queues get_data with the state data and DateTime.Now + 5 seconds (or whatever time) 

When the last function is executed, it sends the results somewhere.

Then you can set a timer that will poll the queue 10 times per second (or the timer time of the next tick will be updated whenever something is added to the queue). It can run individual tasks as needed.

The new Async CTP may already have this thing: "complete the task on time." It might be worth exploring it.

Regarding progress in reports, each function can report progress at startup (i.e., "logging in" ... "waiting 5 seconds to receive data" ... "receiving data", etc.) . If you want, you can force the timer to scroll through the priority queue periodically and let you know when specific tasks will be performed. Although this may be redundant.

And what you heard is correct: Thread.Sleep is an exceptionally bad idea, especially when you work with thread pool threads.

+1
source share

Have you considered using a timer (from System.Timers) to do intermediate "remaining time" updates? Each of your tasks could set the expected time to the completion value, then your timer task could be responsible for counting and updating the user interface as needed. No Thread.Sleep is required, and Timer will execute its Tick code in the thread pool thread.

0
source share

All Articles