C # getting results from asynchronous call
I have an API that I am working with and it has limited documentation. I was told that some of the methods it executes are called asynchronously.
How can I get the result of these async calls. Note that I am not doing anything special to call them, the API handles the asynchronous part. But I cannot get a response from these calls - I am assuming they are on a different thread.
UPDATE - I've included some of the code below. The API uses an event procedure for the callback, but it never fires.
public partial class Window1 : Window
{
ClientAppServer newServer= new ClientAppServer();
public Window1()
{
InitializeComponent();
newServer.ReceiveRequest += ReadServerReply;
}
private void ReadServerReply(RemoteRequest rr)
{
MessageBox.Show("reading server reply");
if ((rr.TransferObject) is Gateways)
{
MessageBox.Show("you have gateways!");
}
}
private void login()
{
newServer.RetrieveCollection(typeof(Gateways), true);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
this.login();
}
a source to share
There are several ways in which operations can be performed asynchronously in .NET. Since you are not posting any details, I will give an overview of more general patterns:
AsyncWaitHandle
Often times you will find (especially in .NET Framework classes) pairs of methods named Begin
and End
(for example, BeginReceive
and EndReceive
).
Calling the begin function returns an object AsyncWaitHandle
that can be used to synchronize threads as normal WaitHandle
(by calling WaitOne
or passing it to static functions WaitHandle.WaitAny
or WaitHandle.WaitAll
), then passed to the appropriate "end" function to get the return value of the function (or, if it did, throws an exception, which was met).
If you are using a simple .NET tool to call a method asynchronously (create a delegate for a function and call BeginInvoke
and EndInvoke
), then this is the approach you need to take. However, most APIs that have built-in support for asynchronous operations will handle the actual part of the asynchronous call for you, leaving you with the properly named functions BeginXXX
and EndXXX
not forcing you to create the delegate yourself.
Example using WaitHandle
:
IAsyncResult result = object.BeginOperation(args);
result.AsyncWaitHandle.WaitOne();
// that will cause the current thread to block until
// the operation completes. Obviously this isn't
// exactly how you'd ordinarily use an async method
// (since you're essentially forcing it to be
// synchronous this way)
returnValue = object.EndOperation(result);
Often, asynchronous methods are associated with events, as shown below.
Developments
Sometimes, calling a method that completes asynchronously will raise an event after it completes. It is sometimes also used in conjunction with an approach AsyncWaitHandle
to deliver a process completion notification. For example, the MSMQ libraries have a function BeginReceive
and EndReceieve
the queue object and event ReceieveCompleted
. When the event fires, it indicates what can then be called EndReceive
by passing the object AsyncWaitHandle
returned from the call to BeginReceive
. to get the actual message that was received.
Either way, you attach to the event and use it just like you would any other event.
Example using AsyncWaitHandle
and events:
(somewhere in the code)
object.OperationComplete += object_OperationComplete;
(in the other place)
IAsyncResult result = object.BeginOperation(args);
// at this point, you can either wait for the event
// to fire, or use the WaitHandle approach as shown
// in the previous example
...
void objectOperationComplete(object sender, AsyncOperationEventArgs e)
{
returnValue = object.EndOperation(e.AsyncResult);
}
They generally work differently ... you can take over the IAsyncResult
returned from the Begin operation yourself, but most libraries will pass that object IAsyncResult
as a property in their concrete class EventArgs
.
It is also common to find the return value as a property in the class EventArgs
. While this value is fine, if the Begin operation returned IAsyncResult
, it is always useful to call the appropriate End function , even if the data you want is in EventArgs
. The End function is usually a way to throw exceptions.
Callbacks
A callback (in .NET) is a delegate that is exposed to an asynchronous function. Callbacks are not only used as asynchronous functions, but in this context they are usually a delegate that you provide when you call a function that it will call when it completes.
Callbacks are similar to events (in that they are both delegate-based), although there is a more one-to-one correlation between method calls and callbacks.
Callback example:
object.BeginOperation(args, OperationComplete);
...
void OperationComplete(SomeObject results)
{
...
}
a source to share
Typically, you would pass a reference to a function that the method will "call back" when it completes. For a great example of this behavior check out BackgroundWorker and RunWorkCompleted . This is specified as a property, not passed as an argument, but the same idea applies.
If you have the source code, or at least the name of the API you are using, we can be more specific.
Here's a basic example of passing in a callback method as an argument:
public SearchForm : Form
{
public void StartSearch(string searchtext)
{
searcher.SearchAsync(searchtext, SearchCompleted);
}
public void SearchCompleted(IList<SearchResult> results)
{
// Called by the async searcher component, possibly on another thread
// Consider marshalling to the UI thread here if you plan to update the UI like this:
if (InvokeRequired)
{
Invoke(new Action<IList<SearchResult>>(SearchCompleted), results);
return;
}
foreach (var result in Results)
{
AddToList(result);
}
}
}
a source to share
There are several idioms for passing asynchronous results. Based on your question, I think you are dealing with methods that accept delegates they invoke ("callbacks").
You must define a method corresponding to the type of the delegate and pass it to the asynchronous method. When it finishes, it calls your delegate, usually passing the results through one or more of the delegate parameters.
For example, if you have this asynchronous method:
public class Foo {
public static void DoSomethingAsynchronous(SimpleCallback simpleCallback) {
// First this method does something asynchronous
// Then it calls the provided delegate, passing the operation results
simpleCallback(true);
}
}
// The result parameter can be much richer - it your primary mechanism for
// passing results back to the caller.
public delegate SimpleCallback(bool result);
You would call it like this:
public static void Main(string[] args) {
Foo.DoSomethingAsynchronous(WriteResultToConsole);
}
// Here your SimpleCallback
public static WriteResultToConsole(bool result) {
Console.WriteLine(result? "Success!" : "Failed!");
}
a source to share