Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What should I do to use Task<T> in .NET 2.0?

.NET 4.0 has the TPL which contains the nice Task class to encapsulate aynchronous programming models. I'm working on an app that must be .NET 2.0, but I want to avoid rewriting Task. Any suggestions?

like image 542
Brian Geihsler Avatar asked Jul 01 '11 16:07

Brian Geihsler


People also ask

How do I run a Task in C#?

To start a task in C#, follow any of the below given ways. Use a delegate to start a task. Task t = new Task(delegate { PrintMessage(); }); t. Start();

When should I use ValueTask?

Here is the rule of the thumb. Use Task when you have a piece of code that will always be asynchronous, i.e., when the operation will not immediately complete. Take advantage of ValueTask when the result of an asynchronous operation is already available or when you already have a cached result.

When should I use async await C#?

If the work you have is I/O-bound, use async and await without Task. Run . You should not use the Task Parallel Library. If the work you have is CPU-bound and you care about responsiveness, use async and await , but spawn off the work on another thread with Task.

Why do we need to use a Task in C#?

A task in C# is used to implement Task-based Asynchronous Programming and was introduced with the . NET Framework 4. The Task object is typically executed asynchronously on a thread pool thread rather than synchronously on the main thread of the application.


2 Answers

I know you said you dont want to rewrite Task, but you can actually create something fairly simple using closures, which behaves somewhat like a Task object. This is what I use:

    public delegate R AsyncTask<R>();

    public static AsyncTask<R> BeginTask<R>(AsyncTask<R> function)
    {
        R retv = default(R);
        bool completed = false;

        object sync = new object();

        IAsyncResult asyncResult = function.BeginInvoke(
                iAsyncResult =>
                {
                    lock (sync)
                    {
                        completed = true;
                        retv = function.EndInvoke(iAsyncResult);
                        Monitor.Pulse(sync); 
                    }
                }, null);

        return delegate
        {
            lock (sync)
            {
                if (!completed)               
                {
                    Monitor.Wait(sync); 
                }
                return retv;
            }
        };
    }

Its a function that calls BeginInvoke() on the delegate you pass in, and returns a function that when called blocks and waits for the result of the function passed in. You'd have to create overloads of this function for different method signatures, of course.

One way to go, you can tweak this to your needs, and add other behaviors too like Continuations, etc. The key is to use closures and anonymous delegates. Should work in .NET 2.0.

EDIT - Here is how you would use it:

    public static string HelloWorld()
    {
        return "Hello World!"; 
    }

    static void Main(string[] args)
    {
        var task = BeginTask(HelloWorld); // non-blocking call

        string result = task(); // block and wait

    }
like image 180
Sean Thoman Avatar answered Oct 12 '22 00:10

Sean Thoman


You will have to use System.Threading.Thread class, you can get the Task class for .net 3.5 but not for .net 2.

Sorry

like image 30
Jethro Avatar answered Oct 12 '22 00:10

Jethro