Click here to Skip to main content
15,846,516 members
Articles / Programming Languages / C#
Article

Type-Strong Asynchronous Execution

Rate me:
Please Sign up or sign in to vote.
3.29/5 (7 votes)
5 Jan 2008CPOL1 min read 25.7K   16   7
Executing a method asynchronously with typed parameters.

Introduction

This static class allows the programmer to run a method asynchronously with a single line of code with typed arguments.

Background

Sometimes, a programmer just want some work to be done in the background, and the .NET framework provides several ways of doing just that. You can start a thread and make it call a function, or you can use the ThreadPool.QueueUserWorkItem, but I always felt it was kind of messy. Using ThreadPool forces you to use a WaitCallback delegate if you want to specify any parameters, these need to be boxed into an object and unboxed in the WaitCallback function called.

So, what I wanted was a simple function to call, Util.RunAsync(function, arg1,arg2,arg3...), in a sort of fire and forget way.

Using the Code

The static class Util contains an overloaded function called RunAsync. It is used as such:

C#
public static void Main(string[] args)
{
    string someString = "Hello There";
    int someInteger = 42;
    DateTime someTime = DateTime.Now;

    Util.RunAsync(Function1, someString, someInteger, someTime);
}

public static void Function1(string aString, int anInteger, DateTime time)
{
    Console.WriteLine("{0} {1} {2}", aString, anInteger, time);
}

Points of Interest

The functionality is achieved using the ThreadPool.QueueUserWorkItem the function, and its arguments are wrapped in an ActionJob object that has a subclass for each amount of arguments usable with Util.RunSync. Because it is based on the Action delegate and the generic versions of it Action<T>, Action<T,V>, Action<T,V,X>, and Action<T,V,X,Y>, it can only execute functions with at most four arguments.

You should be able to change the code to work as a Work Queue for invoking with Windows Forms. Instead of running ThreadPool.QueueUserWorkItem, you could do something like this:

C#
public static void DoInvoke<T, V, X, Y>(
              this System.Windows.Forms.Control control, 
              Action<T, V, X, Y> function, T a, V b, X c, Y d)
{
    if (control.InvokeRequired)
    {
        control.Invoke(function, a, b, c, d);
    }
    else
    {
        function(a, b, c, d);
    }
}

Conclusion

That's it. I like this little convenience, and I hope you do too :)

History

  • 5 January 2008: Article submitted.

License

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


Written By
Other Aalborg University
Denmark Denmark
Jacob is a Computer Science student at Aalborg University Denmark.

He has a special interest in Object Oriented and Managed programming languages such as Java and especially C#.

Jacob has been developing software professionally and for fun in his spare time for more than 7 years during his studies.

Comments and Discussions

 
QuestionError: Using the generic type 'System.Action<t>' requires '1' type arguments</t> Pin
CoderJ19-Feb-08 3:04
CoderJ19-Feb-08 3:04 
GeneralRe: Error: Using the generic type 'System.Action' requires '1' type arguments Pin
Jacob Korsgaard19-Feb-08 4:26
Jacob Korsgaard19-Feb-08 4:26 
GeneralRe: Error: Using the generic type 'System.Action' requires '1' type arguments Pin
CoderJ19-Feb-08 4:49
CoderJ19-Feb-08 4:49 
GeneralRe: Error: Using the generic type 'System.Action' requires '1' type arguments Pin
ml_black24-Feb-10 8:22
ml_black24-Feb-10 8:22 
QuestionAn easier way? Pin
Henrik Jonsson7-Jan-08 8:51
Henrik Jonsson7-Jan-08 8:51 
AnswerRe: An easier way? Pin
Jacob Korsgaard8-Jan-08 1:27
Jacob Korsgaard8-Jan-08 1:27 
It doesn't seem like a bad idea, but after I googled it a little I'm worried that calling BeginInvoke without calling EndInvoke might result in a memory leak, see: http://www.yoda.arachsys.com/csharp/threads/threadpool.shtml[^]

It is certainly an idea that can be used to create an asynchronous execution of Func<t> delegates. Because it would allow you to End the IASyncResult and get a return value.

I applied the job idea to running a Func<v,t> asynchronously:
<br />
    public static void RunAsync<t,v>(Func<v, t=""> function, Action<t> callBack, V a)<br />
    {<br />
        FuncJob<v,t> job = new FuncJob<v, t="">(function, callBack);<br />
        function.BeginInvoke(a, new AsyncCallback(job.End), job);<br />
    }<br />
<br />
    public class FuncJob<v,t><br />
    {<br />
        public Func<v,t> Func { get; protected set; }<br />
        public Action<t> Callback { get; protected set; }<br />
        public FuncJob(Func<v,t> func, Action<t> callback) <br />
        {<br />
            this.Func = func;<br />
            this.Callback = callback;<br />
        }<br />
<br />
        public void End(IAsyncResult result)<br />
        {<br />
            FuncJob<v,t> job = (FuncJob<v,t>)result.AsyncState;<br />
<br />
            T a = job.Func.EndInvoke(result);<br />
<br />
            job.Callback(a);<br />
        }<br />
    }<br />
</v,t></v,t></t></v,t></t></v,t></v,t></v,></v,t></t></v,></t,v>


This RunAsync function takes a Func<v,t> delegate to run and a Action<t> to call when execution of the func has ended. It is not as "fire and forget" as the action idea, but it does allow you to get a result and apply it, all with type safety.
GeneralRe: An easier way? Pin
Henrik Jonsson10-Jan-08 9:47
Henrik Jonsson10-Jan-08 9:47 

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.