Wait task for x amount of time and report progress Wait task for x amount of time and report progress wpf wpf

Wait task for x amount of time and report progress


The solution is to treat it as async callback, rather than a synchronous wait.If you are on the Async CTP, the right way would be to:

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

This 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                  );    }

On calling this with Track(timeout: 5, frequency: 1, item: "http://example.com/?"), the output produced 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


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

Your background thread can send updates to UI with async delegates, but the calling thread will wait it until either thing happens:

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

or

2) the waiting thread timeouts (timeout value is set as parameter to WaitOne() -method).


Rather than having a single task perform all of those half-dozen functions (login, etc.), make each function a separate task. You can then create a priority queue, ordered by time. When you want to start one of these meta-tasks, you place its first function into a queue along with the state data (i.e. url, user id, password, etc.).

As each function is completed, it queues the next function to be performed. So if the first two functions are login and get_data, you'd have:

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

When the last function executes, it posts the results somewhere.

You can then set up a timer that will poll the queue 10 times per second (or have the timer's next tick time be updated whenever something is added to the queue). It can start individual tasks as required.

The new Async CTP might have this kind of thing already: a "execute task at time". Might be worth looking into it.

As for reporting progress, each function can report progress when it starts (i.e. "logging in" ... "waiting 5 seconds to get data" ... "getting data," etc.) If you want, you can make the timer thread walk the priority queue periodically and report when particular tasks will be executed. Although that might be overkill.

And what you heard is right: Thread.Sleep is an exceptionally bad idea, especially when you're working with thread pool threads.