Click here to Skip to main content
15,896,111 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi
I need to have my own C# function in both an awaitable async version and in a version that takes a callback function as a parameter and can be called from multiple threads at the same time. The callback version must be based on the async version.

My awaitable function is:

public async Task<MyClass> GetDocumentAsync(long ID)
{
//I already have this function.
}

GetDocumentAsync(...) must be turned into

public void GetDocumentWithCallback(Action<MyClass> callback, long ID)
{
//1. Can be called from multiple threads at the same time.
//2. Must be none-blocking.
//3. Must be based on a call to the awaitable version GetDocumentAsync(...)
//Please help me with writing this function??
}

I hope someone can help my writing GetDocumentWithCallback(...)
Posted
Updated 19-Jan-16 3:56am
v2

1 solution

How about something like this:
C#
public void GetDocumentWithCallback(Action<MyClass> callback, long ID)
{
    Task<MyClass> task = GetDocumentAsync(ID);
    task.ContinueWith(t => callback(t.Result));
}

NB: Unlike the async version, callback will not be executed in the same context as the caller. That means you won't be able to access the UI in a Windows Forms / WPF application, and HttpContext.Current will not be set in an ASP.NET application.

If that's a problem, you'll have to explicitly capture and restore the context:
C#
public void GetDocumentWithCallback(Action<MyClass> callback, long ID)
{
    Task<MyClass> task = GetDocumentAsync(ID);
    ExecutionContext context = ExecutionContext.Capture();
    ContextCallback contextCallback = state => callback((MyClass)state);
    task.ContinueWith(t => ExecutionContext.Run(context, contextCallback, t.Result));
}
 
Share this answer
 
v2
Comments
Henrik R L 19-Jan-16 12:33pm    
Hi Richard Deeming,

Thanks for the answer. I will try that.

One more thing... Can two threads call GetDocumentWithCallback() below at the same time? Is it thread safe?

public void GetDocumentWithCallback(Action<myclass> callback, long ID)
{
Task<myclass> task = GetDocumentAsync(ID);
ExecutionContext context = ExecutionContext.Capture();
ContextCallback contextCallback = state => callback((MyClass)state);
task.ContinueWith(t => ExecutionContext.Run(context, contextCallback, t.Result));
}

Will there be any problem in calling GetDocumentWithCallback() above in a loop on the UI thread like shown below?

for(int ID=1;ID<100;ID++)
{
GetDocumentWithCallback(UpdateGUI, ID);
}

void UpdateGUI(MyClass docInfo)
{
//Update GUI for specific document on each callback
}
Richard Deeming 19-Jan-16 12:38pm    
Assuming GetDocumentAsync is thread-safe, there shouldn't be any problems.

With the loop in the UI thread, the callbacks will be executed sequentially. If more than one task completes simultaneously, the callbacks will be queued up waiting to execute on the UI thread.
Henrik R L 19-Jan-16 12:41pm    
Hi Richard

Thanks a lot :-)

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900