Initializing AsyncExecutor
To initialize the AsyncExecutor an instance has to be created e.g. in a constructor of your view or view model - i.e. called anywhere where it's called on the UI thread.

A method has to be passed to the constructor which can be called by the AsyncExecutor when an exception ocurrs.
Remark: If the application works correctly this handler should never be called - it's just there to avoid that the application dies silently after an exception is thrown on a worker thread.

E.g. 
        public ViewModel()
        {
            Async = new AsyncExecutor(ExceptionHandler);   
        }

        public AsyncExecutor Async { get; private set; }

        private void ExceptionHandler(Exception ex)
        {
            MessageBox.Show("Unforeseen Exception: " + ex.ToString());
        }



Creating an async method
Methods that shall be executed by the AsyncExecutor have to have a return value of type
IEnumerator<SwitchThread>
i.e. they can't have other return values - which would not make much sense anyway because they are executed asynchronously.
They can also not have out parameters for the same reason.
They can of course have input paramters.

Switching between the threads is done using yield return statements.


Example method:
private IEnumerator<SwitchThread> GetPersonsAsync()
{
            yield return SwitchThread.ToUI;
            PersonCollection.Clear();
            StatusMessage = "Loading Persons...";

            yield return SwitchThread.ToWorker;
            List<string> persons = provider.GetPersons();

            yield return SwitchThread.ToUI;
            foreach (var name in persons)
            {
                PersonCollection.Add(new Person { Name = name });
            }

            StatusMessage = "Finished loading persons";
}

Here the provider.GetPersons() call is done on the worker thread.

Please note that the return value persons can be used in the same method on the UI thread.

Starting an async method
Example:
Async.StartExecution(GetPersonsAsync());

Please note that parameters could also be handed to the method if needed.

Starting an async method from an async method
From time to time it's nice to be able to refactor huge async methods into single async methods.
This can be achieved by using the AsyncExecutor.Execute method: It uses the current thread as worker thread - i.e. allows for quasi synchronous execution.
When using this please make sure that the Execute method is called on the worker thread.

Example:
yield return SwitchThread.ToWorker;
Async.Execute(GetPersonsAsync());

It is also possible to start other async methods asynchronously by using AsyncExecutorStartExecution.

Ending Execution of an async method
If an async method execution  shall be ended immediately (e.g. after an error occurred), yield break can be used - as in any other IEnumerator.

How to do find out that the AsyncExecutor is busy
The AsyncExecutor has a flag called "IsBusy".

When the flag is changed the PropertyChanged event is fired. I.e. this is WPF binding "friendly".

Parallel execution
The StartExecution method can be called multiple times. Each is then using a separate worker thread.
The IsBusy flag is reset to false when all such executions have ended.

Last edited Nov 4, 2011 at 10:11 AM by RalfHoffmann, version 6

Comments

No comments yet.