Click here to Skip to main content
15,878,959 members
Articles / Programming Languages / C#
Tip/Trick

Generic Async Factory

Rate me:
Please Sign up or sign in to vote.
3.18/5 (5 votes)
24 Nov 2006CPOL2 min read 55.4K   181   18   17
A Generic Extensible Async Factory

Introduction

Factories are used for creating objects. Different objects would have different creational logic. There are instances where the object creation might consume time and you may want to move the logic onto a non-blocking thread to keep the application responsive. The AsyncFactory is a step towards that. You can have different factory implementations, without worrying about the asynchronous execution logic.

The AsyncFactory

The AsyncFactory is a Generic class which can be sub classed for any factory implementation, that needs to executed asynchronously. The AysncFactory is an Abstract Generic class with a single protected abstract Create method. The method accepts a type parameter <P> and returns a type <T>. This method needs to be overridden in the subclass with specific implementation of your interest with the appropriate parameter and return types.

C#
public abstract class AysncFactory<TReturn, TParam>
{
  protected abstract TReturn Create(TParam createParams); 
}

Internally the AysncFactory uses the age old .NET ThreadPool and queues the creation logic on a non-blocking thread. It has a BeginCreate and an EndCreate implementation, which eventually gets exposed to the clients. They follow the conventional BeginXXX and EndXXX signature and implementation.

C#
public IAsyncResult BeginCreate(AsyncCallback callback, TParam createParams);
public TReturn EndCreate(IAsyncResult asyncResult);

There's an CreateAsyncResult class that implements IAsyncResult. It contains a private ManualResetEvent member to block the client when the EndCreate is called, till the creation logic is completed. The BeginCreate queues an internal AsyncCreate method which actually invokes the overridden Create method. Once the Create method completes, the AsyncCreate sets the flag on the WaitHandle, invokes the callback and returns. The EndCreate calls the WaitOne on the WaitHandle, which blocks till the Create function completes and then the set on the WaitHandle is called to signal all the blocked threads.

The clients call the BeginCreate with the callback and the parameters that need to be passed to the create method. The BeginCreate returns an IAsyncResult, which is needed to be passed to the EndCreate to trigger the completion. The EndCreate blocks until the creation is completed and returns the created object.

Sample Implementation

WinWordApplicationFactory is a factory class which creates instances of WinWord Application object. The Create method takes a boolean value to turn on/off the visible property, and returns an instance of ApplicationClass:

C#
public class WinWordApplicationFactory : AsyncFactory<MSWordApplication, bool>
{
    protected override MSWordApplication Create(bool isVisible)
    {
        object oMissing = System.Reflection.Missing.Value;
        MSWordApplication msWord = new MSWordApplication();
        msWord.Visible = isVisible;
        return msWord;
    }
}

Client

C#
private ApplicationClass wordApp;
private WinWordApplicationFactory appFactory;
public WinWordFactoryClient()
{
    this.appFactory = new WinWordApplicationFactory();
    this.CreateWordInstance();
}

private void CreateWordInstance()
{
    //Call the BeginCreate of the factory with a callback.
    appFactory.BeginCreate(new AsyncCallback(this.AppCreateCallback), true);
}

public void AppCreateCallback(IAsyncResult result)
{
    //Call the EndCreate to get the object created by the factory.
    this.wordApp = appFactory.EndCreate(result);

    //start using the wordApp instance.
    //this.wordApp.Documents.Open(....
}

Conclusion

Generally Factory classes are singleton. I'm on the way to implementing the same. Till then, happy coding!

History

  • 24th November, 2006: Initial post

License

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


Written By
Architect
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Bugtypo on IAyncResult Pin
Cœur13-May-14 2:21
Cœur13-May-14 2:21 
GeneralRe: typo on IAyncResult Pin
Krishnan Srinivasan19-May-14 18:17
Krishnan Srinivasan19-May-14 18:17 
GeneralWaitOne Pin
jbrathwaite29-Nov-06 9:38
jbrathwaite29-Nov-06 9:38 
GeneralRe: WaitOne Pin
Krishnan Srinivasan30-Nov-06 16:26
Krishnan Srinivasan30-Nov-06 16:26 
Thanks John. To answer your question, the waithandle blocks all the calling threads till the Set is called. If you look at the code the ManualResetEvent's instance gets created in the constructor of CreateAysncResult, with a boolean false, which means the state is non-signalled. So any call to WaitOne will result in a block beyond this point till the Set is called.

The BeginCreate calls the CreateAsync, which inturn invokes the overridden Create implementation. Only when this returns, would the Set on the WaitHandle would be called.

Meanwhile, BeginCreate returns immediately, invoking the callback. Inside the callback the user calls the EndCreate, which calls the WaitOne on the WaitHandle. So this would block till the CreateAsync of the factory calls the Set, which eventually would happen only when the overriden Create returns.

It may appear that the Set on the ManualResetEvent is being called before Waitone, because the BeginCreate returns immediately resulting in EndCreate being invoked from the callback, while the actual "Creation" task is happening on a secondary thread.

Hope my explanation clarifies your question.

Regards,
Krishnan.
GeneralRe: WaitOne Pin
jbrathwaite2-Dec-06 17:12
jbrathwaite2-Dec-06 17:12 
GeneralRe: WaitOne Pin
Krishnan Srinivasan3-Dec-06 3:54
Krishnan Srinivasan3-Dec-06 3:54 
GeneralRe: WaitOne Pin
jbrathwaite2-Dec-06 22:14
jbrathwaite2-Dec-06 22:14 
GeneralRe: WaitOne Pin
Krishnan Srinivasan3-Dec-06 3:49
Krishnan Srinivasan3-Dec-06 3:49 
GeneralRe: WaitOne Pin
jbrathwaite3-Dec-06 23:02
jbrathwaite3-Dec-06 23:02 
GeneralRe: WaitOne Pin
Krishnan Srinivasan5-Dec-06 2:46
Krishnan Srinivasan5-Dec-06 2:46 
GeneralAnother take Pin
Alexey A. Popov24-Nov-06 23:05
Alexey A. Popov24-Nov-06 23:05 
GeneralRe: Another take Pin
Krishnan Srinivasan30-Nov-06 16:29
Krishnan Srinivasan30-Nov-06 16:29 
GeneralThanks! Pin
Alexey A. Popov24-Nov-06 21:08
Alexey A. Popov24-Nov-06 21:08 
GeneralRe: Thanks! Pin
Krishnan Srinivasan25-Nov-06 3:10
Krishnan Srinivasan25-Nov-06 3:10 
GeneralRe: Thanks! Pin
Alexey A. Popov27-Nov-06 7:18
Alexey A. Popov27-Nov-06 7:18 
GeneralRe: Thanks! Pin
Krishnan Srinivasan30-Nov-06 15:40
Krishnan Srinivasan30-Nov-06 15:40 
GeneralRe: Thanks! Pin
sadavoya27-Nov-06 7:18
sadavoya27-Nov-06 7:18 

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

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