0

Suppose I have the following method signature for an Async method:

public IAsyncResult MyAsyncMethod(AsyncCallback asyncCallback, object state);

And, therefore, I use the following code to call it and assign it a state object and a callback:

public class test
{
    // Private class to hold / pass-through data used by Async operations
    private class StateData
    {
        //... Whatever properties I'll need passed to my callback ...
    }

    public void RunOnSeparateThread()
    {
        StateData stateData = new StateData { ... };
        MyAsyncMethod(m_asyncCallback, stateData);
    }

    private AsyncCallback m_asyncCallback = new AsyncCallback(AsyncComplete);
    private static void AsyncComplete(IAsyncResult result)
    { 
        // Whatever stuff needs to be done after completion of Async method
        // using data returned in the stateData object
    }
}

I'm looking to do the same thing using Task Parallel Library and am not certain how to do it. What would be the correct code to achieve the same result, being:

  1. Run MyAsyncMethod on a separate thread
  2. On completion have a state object returned with it passed to the next method - In this case AsyncComplete

Or is there a better way to accomplish the same result?

Also, although this is written in C#, I'm equally comfortable in VB and C#, so any answer would be greatly appreciated.

Thank you and hopefully this makes sense.

4
  • 2
    This should help you get started: albahari.com/threading/part5.aspx#_Task_Parallelism Commented Apr 23, 2015 at 13:07
  • Thanks so much, @JoshL., looks like a very useful link - Looking into it now. Commented Apr 23, 2015 at 13:11
  • Maybe this on MSDN is also good. Commented Apr 23, 2015 at 13:12
  • @JohnBustos Yeah, helped me a lot for sure and it's pretty straightforward. Commented Apr 23, 2015 at 13:13

1 Answer 1

1

Suppose I have the following method signature for an Async method:

public IAsyncResult MyAsyncMethod(AsyncCallback asyncCallback, object state);

I would expect the return value to be Task<T> (IAsyncResult is normally returned from the BeginXYZ when there is a matching EndXYZ in the original .NET async pattern), and not taking a callback. (As presented it seems to be a bit of one pattern and a bit of another.)

If my expectation is right then, just call the method and use the retuned Task<T>.

If it is really a IAsyncResult then TaskFactory has a helper method: FromAsync which amongst its many overloads can take an IAsyncResult and an Action<IAsyncResult>.

So your code becomes:

var ia = MyAsyncMethod(() => {}, null);
var t = Task.Factory.FromAsync(ia, x => { 
    // called with ia from MyAsyncMethod on completion.
    //  Can close over any state
});

// ...
var result = (TypeofResult)t.Result;
Sign up to request clarification or add additional context in comments.

5 Comments

t.Result would block. I'd advise to await t instead, avoiding potential deadlocks as well.
@YuvalItzchakov What about for .Net Frameworks below 4.5? Since I don't think await is available before then.
@Josh If you're on .NET 4.0 and use VS2012 and above, you have the Bcl.Async library via NuGet. If you're on .NET 4.0 and VS2010, you can use Task.ContinueWith to access the completed task.
@YuvalItzchakov Indeed, but I've assumed that, as the Q asks about using TPL, this is covered in the ellipses because if there isn't something else to be done concurrently then why use TPL?
This question isn't about parallelism, it's about concurrency and how to convert the APM pattern to the TAP. He can use FromAsync because it provides exactly what he needs to do, transform the former to the latter.

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.