0

I found that for expensive IO bound operation I can use TaskCompletionSource

as shown here http://msdn.microsoft.com/en-us/library/hh873177.aspx#workloads

But the example shown is only waiting for some time and return DateTime.

public static Task<DateTimeOffset> Delay(int millisecondsTimeout)
{
 TaskCompletionSource<DateTimeOffset> tcs = null;
 Timer timer = null;

 timer = new Timer(delegate
 {
    timer.Dispose();
    tcs.TrySetResult(DateTimeOffset.UtcNow);
 }, null, Timeout.Infinite, Timeout.Infinite);

 tcs = new TaskCompletionSource<DateTimeOffset>(timer);
 timer.Change(millisecondsTimeout, Timeout.Infinite);
 return tcs.Task;
}

Above code waits for timeout. I have a database call which I want to fire in the above way, but little confused in how to write it:

   using (var context = new srdb_sr2_context())
   {
      return context.GetData("100", "a2acfid");
   }

I wrote the function as below, but not sure if this is correct way of doing it:

TaskCompletionSource<IList<InstructorsOut>> tcs = null;
        Timer timer = null;

        timer = new Timer(delegate
        {
            timer.Dispose();

            //prepare for expensive data call
            using (var context = new srdb_sr2_context())
            {
                var output = context.GetData("100", "a2acfid");

                //set the result
                tcs.TrySetResult(output);
            }  

        }, null, Timeout.Infinite, Timeout.Infinite);

        tcs = new TaskCompletionSource<IList<InstructorsOut>>(timer);
        timer.Change(0, Timeout.Infinite);
        return tcs.Task;

Any help would be appreciated.

1
  • The reason for the confusion is that TaskCompletionSource is NOT about running IO bound operations. It's about providing a Task-based wrapper over other asynchronous operations, eg. timer delays, events, callbakcs. Besides, database operations are NOT IO bound operations. They actually have very little IO while they wait for results Commented Aug 20, 2013 at 13:58

1 Answer 1

1

Your code doesn't make much sense to me. Timer is useful if you want to execute the code after some time, but that's not what you need here.

If you want to execute an operation on a background thread, you can use Task.Run():

Task<IList<InstructorsOut>> GetDataBackground()
{
    return Task.Run(() =>
    {
        using (var context = new srdb_sr2_context())
        {
            return context.GetData("100", "a2acfid");
        }  
    });
}

Using a background thread this way can be useful in UI apps, where you don't want to block the UI thread. But if you have something like ASP.NET application, this won't actually give you any performance or scalability improvements. For that, the GetData() method would have to be made truly asynchronous.

Sign up to request clarification or add additional context in comments.

4 Comments

That's exactly my question is: How to make GetData() truly asynchronous. I have also added the MSDN link which shows using Timer to do it.
Well, you can't (assuming you can't directly modify GetData()). The author of the library that contains GetData() has to do that.
GetData() is entity framework Function Import. So I can't really do anything there since EF 5.0 does not support async operations.
@SanjaySutar In that case, there's nothing you can do (except for switching to EF 6.0).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.