Rohit
Rohit

Reputation: 10236

creating a threadless task using Taskcompletion source

I am getting my hands dirty with TPL.I stumbled upon a topic in TPL called TaskCompletionSource which is one of the ways to create a Task and it give you more control over the task by allowing developers in setting result,exception etc etc. Here is an example using task completion source

   public static Task<int> RunAsyncFunction(Func<int> sampleFunction)
    {
        if (sampleFunction == null)
            throw new NullReferenceException("Method cannot be null");

        var tcs = new TaskCompletionSource<int>();

        ThreadPool.QueueUserWorkItem(_ =>
        {
            try
            {
                int result = sampleFunction();
                tcs.SetResult(result);
            }
            catch (Exception ex)
            {
                tcs.SetException(ex);
            }
        });

        return tcs.Task;
    }

However this is not truly asynchronus programming.It is asynchronus programming using multithreading .How can I convert this example to get it run on a single thread rather than multiple threads ? or is there any other example I can follow?

Upvotes: 0

Views: 271

Answers (2)

i3arnon
i3arnon

Reputation: 116548

TaskCompletionSource doesn't make your code asynchronous. It's a utility to enable someone else to asynchronously await your operation.

Your operation needs to already be asynchronous on its own. For example if it's in an older paradigm, like the BeginXXX/EndXXX one.

TaskCompletionSource is mostly used to convert different types of asynchronous programming into Task based asynchronous programming.

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1062800

For it to be asynchronous, it needs some capacity to be completed independently in the future. That is typically via one of two things:

  • via a callback from an operation such as socket IO, file IO, a system timer, etc (some external source that can cause reactivation)
  • a second thread (possibly a queued work pool thread, like in your example)

If you only have a single thread, and no external callback, then there really isn't any need or sense in using Task<T>. However, you can still expose that by simply performing the calculation now, and setting the result now - or more simply: using Task.FromResult.

However, the code you have shown is genuinely asynchronous - or more specifically: the Task<T> that you return is. It perhaps isn't the greatest use-case, but there's nothing inherently wrong with it - except that your entire method can be hugely simplified to:

return Task.Run(sampleFunction);

The Task.Run<T> method:

Queues the specified work to run on the ThreadPool and returns a task or Task handle for that work.

Normally, if I'm using TaskCompletionSource, it is because I am writing IO-callback based tasks, not ThreadPool based tasks; Task.Run is fine for most of those.

Upvotes: 3

Related Questions