Click here to Skip to main content
Click here to Skip to main content

Simplify Asynchronous Method Calls by Using a Base Class

, 11 Dec 2010
Rate this:
Please Sign up or sign in to vote.
A template for calling methods asynchronously and returning the results on the caller's thread.

Introduction

Whenever you have a long running process, it's usually a good idea to have it process in a background thread. This keeps your application responsive. If it's a piece of code that is only being called from a few spots, the BackgroundWorker is often the best solution. If it's a class library that will be called from lots of different applications, I prefer to encapsulate the threading within the class.

Background

The basic premise is to create an abstract base class. Every method that can be called asynchronously will have a corresponding Async method and Completed event. This allows the method to be called either asynchronously or not depending on the needs of the caller.

Using the Code

To use the code, you'll need to create the new abstract base class and threaded wrapper methods for all methods that need asynchronous execution.

public event EventHandler<myasynceventargs> MyMethodComplete;

protected void FireMyMethodComplete(int result, object state)
{
    ...
}

public abstract int MyMethod(string stringParameter, int intParameter);

public void MyMethodAsync(string stringParameter, int intParameter, object state) { ... }

You will need the abstract declaration and event declarations for each method to be called asynchronously. Any method that doesn't need to be threaded should not be declared in this base class.

public void MyMethodAsync(string stringParameter, int intParameter, object state)
{
    MyMethodParameters parameters = new MyMethodParameters()
    {
        StringParameter = stringParameter,
        IntParameter = intParameter,
        //Other Parameters Use by the Method
        ...
        CallerStateObject = state,        
        CallingDispatcher = 
          System.Windows.Threading.Dispatcher.CurrentDispatcher        
    };
    
    System.Threading.ThreadPool.QueueUserWorkItem(MyMethodThreaded, parameters);
}

The key to this is the dispatcher. By storing a reference to the calling thread's dispatcher, we can later raise events on that thread.

private void MyMethodThreaded(object p)
{
    MyMethodParameters parameters = (MyMethodParameters)p;
    
    int result = MyMethod(parameters.StringParameter, parameters.IntParameters);
    
    parameters.CallingDispatcher.BeginInvoke(
        new Action<int,>(FireMyMethodCompleteEvent),
        result,
        parameters.CallerStateObject);
}

Within the threaded method, we call the actual method. We then use the dispatcher we saved earlier to call the event handler on the proper thread. As promised, this keeps the class with the business logic simple.

public class MyClass : MyAsyncBaseClass
{
    public override int MyMethod(int stringParameter, int intParameter)
    {
        //Your long running process here
        return 42;        
    }
}

Using the class is also simple.

...
    
MyClass _myClass = new MyClass();
_myClass.MyMethodComplete += MyClass_MyMethodComplete

...

_myClass.MyMethodAsync(AStringParameter, AnIntParameter, 
                       APassthroughStateObject);

...

void MyClass_MyMethodComplete(object sender, MyAsyncEventArgs e)
{
    //Process results here
}

Conclusion

You've no doubt noticed this results in far more code than simply using the BackgroundWorker. However, it requires less code in the projects which consume your class. For a class which is reused frequently, there will be less cumulative code.

History

  • 17th October, 2009: Initial post
  • 9th December, 2010: Article updated

License

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

About the Author

aef123
Software Developer (Senior) White Box Technologies
United States United States
No Biography provided

Comments and Discussions

 
GeneralWhy dont you just derive from Backgroundworker... Pinmemberoldpasch9-Dec-10 3:24 
GeneralRe: Why dont you just derive from Backgroundworker... Pinmemberaef1239-Dec-10 3:51 
GeneralRe: Why dont you just derive from Backgroundworker... Pinmemberklinkenbecker10-Nov-11 8:14 
GeneralConlcusion is kind of confusing Pinmemberaef12311-Nov-09 7:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 11 Dec 2010
Article Copyright 2009 by aef123
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid