IAsyncResult.AsyncWaitHandle.WaitOne() completes ahead of callback - c#

Here is the code:
class LongOp
{
//The delegate
Action longOpDelegate = LongOp.DoLongOp;
//The result
string longOpResult = null;
//The Main Method
public string CallLongOp()
{
//Call the asynchronous operation
IAsyncResult result = longOpDelegate.BeginInvoke(Callback, null);
//Wait for it to complete
result.AsyncWaitHandle.WaitOne();
//return result saved in Callback
return longOpResult;
}
//The long operation
static void DoLongOp()
{
Thread.Sleep(5000);
}
//The Callback
void Callback(IAsyncResult result)
{
longOpResult = "Completed";
this.longOpDelegate.EndInvoke(result);
}
}
Here is the test case:
[TestMethod]
public void TestBeginInvoke()
{
var longOp = new LongOp();
var result = longOp.CallLongOp();
//This can fail
Assert.IsNotNull(result);
}
If this is run the test case can fail. Why exactly?
There is very little documentation on how delegate.BeginInvoke works. Does anyone have any insights they would like to share?
Update
This is a subtle race-condition that is not well documented in MSDN or elsewhere. The problem, as explained in the accepted answer, is that when the operation completes the Wait Handle is signalled, and then the Callback is executed. The signal releases the waiting main thread and now the Callback execution enters the "race". Jeffry Richter's suggested implementation shows what's happening behind the scenes:
// If the event exists, set it
if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
// If a callback method was set, call it
if (m_AsyncCallback != null) m_AsyncCallback(this);
For a solution refer to Ben Voigt's answer. That implementation does not incur the additional overhead of a second wait handle.

The ASyncWaitHandle.WaitOne() is signaled when the asynchronous operation completes. At the same time CallBack() is called.
This means that the the code after WaitOne() is run in the main thread and the CallBack is run in another thread (probably the same that runs DoLongOp()). This results in a race condition where the value of longOpResult essentially is unknown at the time it is returned.
One could have expected that ASyncWaitHandle.WaitOne() would have been signaled when the CallBack was finished, but that is just not how it works ;-)
You'll need another ManualResetEvent to have the main thread wait for the CallBack to set longOpResult.

As others have said, result.WaitOne just means that the target of BeginInvoke has finished, and not the callback. So just put the post-processing code into the BeginInvoke delegate.
//Call the asynchronous operation
Action callAndProcess = delegate { longOpDelegate(); Callafter(); };
IAsyncResult result = callAndProcess.BeginInvoke(r => callAndProcess.EndInvoke(r), null);
//Wait for it to complete
result.AsyncWaitHandle.WaitOne();
//return result saved in Callafter
return longOpResult;

What is happening
Since your operation DoLongOp has completed, control resumes within CallLongOp and the function completes before the Callback operation has completed. Assert.IsNotNull(result); then executes before longOpResult = "Completed";.
Why? AsyncWaitHandle.WaitOne() will only wait for your async operation to complete, not your Callback
The callback parameter of BeginInvoke is actually an AsyncCallback delegate, which means your callback is called asynchronously. This is by design, as the purpose is to process the operation results asynchronously (and is the whole purpose of this callback parameter).
Since the BeginInvoke function actually calls your Callback function the IAsyncResult.WaitOne call is just for the operation and does not influence the callback.
See the Microsoft documentation (section Executing a Callback Method When an Asynchronous Call Completes). There is also a good explanation and example.
If the thread that initiates the asynchronous call does not need to be the thread that processes the results, you can execute a callback method when the call completes. The callback method is executed on a ThreadPool thread.
Solution
If you want to wait for both the operation and the callback, you need to handle the signalling yourself. A ManualReset is one way of doing it which certainly gives you the most control (and it's how Microsoft has done it in their docs).
Here is amended code using ManualResetEvent.
public class LongOp
{
//The delegate
Action longOpDelegate = LongOp.DoLongOp;
//The result
public string longOpResult = null;
// Declare a manual reset at module level so it can be
// handled from both your callback and your called method
ManualResetEvent waiter;
//The Main Method
public string CallLongOp()
{
// Set a manual reset which you can reset within your callback
waiter = new ManualResetEvent(false);
//Call the asynchronous operation
IAsyncResult result = longOpDelegate.BeginInvoke(Callback, null);
// Wait
waiter.WaitOne();
//return result saved in Callback
return longOpResult;
}
//The long operation
static void DoLongOp()
{
Thread.Sleep(5000);
}
//The Callback
void Callback(IAsyncResult result)
{
longOpResult = "Completed";
this.longOpDelegate.EndInvoke(result);
waiter.Set();
}
}
For the example you have given, you would be better not using a callback and instead handling the result in your CallLongOp function, in which case your WaitOne on the operation delegate will work fine.

The callback is executed after the CallLongOp method. Since you only set the variable value in the callback, it stands to reason that it would be null.
Read this :link text

I had the same issue recently, and I figured another way to solve it, it worked in my case. Bacially if the timeout doesn't borther you, re-check the flag IsCompleted when Wait Handle is timeout. In my case, the wait handle is signaled before blocking the thread, and right after the if condition, so recheck it after timeout will do the trick.
while (!AsyncResult.IsCompleted)
{
if (AsyncWaitHandle.WaitOne(10000))
break;
}

Related

Usage criteria for IAsyncResult.IsCompleted, iftAR.AsyncWaitHandle.WaitOne and AsyncCallback

I am learning the async concept of delegates and here I am confused on the difference between using the IAsyncResult.IsCompleted, iftAR.AsyncWaitHandle.WaitOne and AsyncCallback (in which you define new function with IAsyncResult as parameter).
I'm confused because suppose you use while loop to check for above 3 values, then in each of the 3 cases, you are checking in while loop whether the particular operation has completed executing. Then, what is the difference between the 3?
CASE 1 Code:
static void Main(string[] args)
{
Console.WriteLine("***** Async Delegate Invocation *****");
// Print out the ID of the executing thread.
Console.WriteLine("Main() invoked on thread {0}.",Thread.CurrentThread.ManagedThreadId);
// Invoke Add() on a secondary thread.
BinaryOp b = new BinaryOp(Add);
IAsyncResult iftAR = b.BeginInvoke(10, 10, null, null);
// This message will keep printing until
// the Add() method is finished.
while(!iftAR.IsCompleted)
{
Console.WriteLine("Doing more work in Main()!");
Thread.Sleep(1000);
}
// Now we know the Add() method is complete.
int answer = b.EndInvoke(iftAR);
Console.WriteLine("10 + 10 is {0}.", answer);
Console.ReadLine();
}
static int Add(int x, int y)
{
// Print out the ID of the executing thread.
Console.WriteLine("Add() invoked on thread {0}.", Thread.CurrentThread.ManagedThreadId);
// Pause to simulate a lengthy operation.
Thread.Sleep(5000);
return x + y;
}
CASE 2 code:If we replace the while loop with foll code:
while (!iftAR.AsyncWaitHandle.WaitOne(1000, true))
{
Console.WriteLine("Doing more work in Main()!");
}
CASE 3 code:If we replace the while loop from CASE 1 with foll code and add the AddComplete method:
while (!isDone)
{
Thread.Sleep(1000);
Console.WriteLine("Working....");
}
static void AddComplete(IAsyncResult itfAR)
{
Console.WriteLine("AddComplete() invoked on thread {0}.", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Your addition is complete");
isDone = true;
}
The IAsyncResult is part of the APM pattern, which in itself has not much to do with delegates, but just uses a delegate for the callback. This pattern needs to be looked at as its own (quite complex) topic.
MSDN
That being said, the difference in summary is the following:
IsComplete is just a flag which lets you poll/check if the operation is complete or if it is still running.
The WaitHandle wraps an operating system primitive and allows to join a thread without using any CPU for the duration of the async operation, optionally with a timeout. When the timeout on WaitOne is set to 0, the operation is basically doing the same as IsComplete but at a much higher overhead cost.
The callback however allows to fire off an operation and "forget" about it; the callback will be called when the operation is complete, therefore allowing to continue at that point without actively polling or waiting. In the callback, the IsComplete will always be true and invoking WaitOne.Join would always immediately return.
Note: in your AddComplete callback, you should invoke the EndInvoke, not just set a synchronisation flag.
So if your use case is a while loop (a "spinning wait"), you should poll the IsComplete flag. The other two are used in other situations.

asnychronous callback

I am new to asynchronous programming. I have a C# dll with an asynchronous method that gets called, takes a function pointer (delegate) and calls this callback function after "result" is calculated.
public delegate void CreatedDelegate(Foo result);
public void CreateAsync(CreatedDelegate createdCallback)
{
Task t = Task.Factory.StartNew(() =>
{
Foo result = ...
createdCallback(result);
});
}
The delegate callback of type "CreatedDelegate" is (in my case) a function pointer to a C++/CLI method that works with the result.
void CreatedCallback(Foo^ result)
{
// do something with result
}
So this asynchronous concept seems to work quite well in most cases, but sometimes I encounter some errors. How can I achieve it if the function "CreateAsync" is called multiple times with different computation effort, that the resulting calls to "CreatedCallback" just happen in the same order as originally "CreateAsync" was called? To make it clearer: The first call to "CreateAsync" should result in the first call to "CreatedCallback" even if a succeeding call of "CreateAsync" is faster and would actually call the callback earlier.
Maybe this can be done by allowing only one active new thread in the asynchronous "CreateAsync" at a time?
To process the callbacks in order, you'll need to implement some queueing of work items. The easiest way is probably to use BlockingCollection type (see MSDN documentation).
Instead of calling the callback, your CreateAsync method would add the task (together with the callback) to the queue:
// Queue to keep tasks and their callbacks
private BlockingCollection<Tuple<Task<Foo>, CreatedDelegate>>
queue = new BlockingCollection<Tuple<Task<Foo>, CreatedDelegate>>()
public void CreateAsync(CreatedDelegate createdCallback) {
Task<Foo> t = Task.Factory.StartNew(() => {
Foo result = ...
return result; });
queue.Add(Tuple.Create(t, createdCallback));
// ..
}
This will only add tasks and callbacks to the queue - to actually call the callback, you'll need another task that waits for the tasks in the queue (in the order in which they were added) and calls the callback:
Task.Factory.StartNew(() => {
while(true) { // while you keep calling 'CreateAsync'
// Get next task (in order) and its callback
Tuple<Task<Foo>, CreatedDelegate> op = queue.Take();
// Wait for the result and give it to callback
op.Item2(op.Item1.Result);
}
}
If order is important, then using Threads might be better:
thread queue = empty
for each task
{
if there are no free 'cpu'
wait on first thread in queue
remove thread from queue
call delegate
create thread
add thread to queue
}
while queue has threads
wait on first thread in queue
remove thread from queue
call delegate

how to give callback function to the Dispatcher.BeginInvoke

I need to use callback function to do some post procesing tasks when the function started with the Dispatcher.BeginInvoke finishes. However i could not find any parameter in Dispatcher.BeginInvoke to accept a callback. Is it possible to give a callback function to Dispatcher.BeginInvoke?
The DispatcherOperation object returned by BeginInvoke has a Completed event on it. Subscribe to that to perform operations upon completion:
var dispatcherOp = Dispatcher.BeginInvoke( /* your method here */);
dispatcherOp.Completed += (s, e) => { /* callback code here */ };
There's a chance the operation will complete before you subscribe, so you can test the Status property for completion after as well:
if (dispatcherOp.Status == DispatcherOperationStatus.Completed) { ... }
It's possible for the operation to be aborted as well, so handling/testing for Aborted may also be appropriate.

Queue a thread in .net

I have 2 functions that needs to be executed one after the other. In this function, async calls are made. How do I go about executing the second function after the async call is completed?
For eg.
public void main()
{
executeFn("1");
executeFn("2"); //I want this to be executed after 1 has finished.
}
private bool executeFn(string someval)
{
runSomeAsyncCode(); //This is some async uploading function that is yet to be defined.
}
You can use Thread.Join.
But then I do not see the point of async execution of those 2 functions as they become sequential.
Let runSomeAsyncCode() return an IAsyncResult and implement the BeginX EndX methods similar to the CLR Asynchronous Programming Model. Use the EndX method to wait for the code to finish executing.
Your async method you're calling must have something to notify the caller when it's completed am I correct? (otherwise it would be just execute and forget, which is unlikely) If so, you simply have to wait for the notification to come up and execute the second method.
try this:
public void main()
{
executeFn("1");
executeFn("2");
}
List<string> QueuedCalls = new List<string>(); // contains the queued items
bool isRunning = false; // indicates if there is an async operation running
private bool executeFn(string someval)
{
if(isRunning) { QueuedCalls.Add(someval); return; } // if there is an operation running, queue the call
else { isRunning = true; } // if there is not an operation running, then update the isRunning property and run the code
runSomeAsyncCode(); //undefined async operation here<-
isRunning = false; //get here when the async is completed, (updates the app telling it this operation is done)
if(QueuedCalls.Count != 0)//check if there is anything in the queue
{
//there is something in the queue, so remove it from the queue and execute it.
string val = QueuedCalls[0];
QueuedCalls.RemoveAt(0);
executeFn(val);
}
}
this way will not block any threads, and will simply execute the queued call when the first finnishs,which is what i believe you want! happy coding! now id recommend running the last section, at where it sets the isRunning to false, inside your async operation, or trigger it with an event or something, the only catch is that peice of code has to be executed when your async operation is completed, so however you want to do that is up to you
You can consider using Generic delegates execute the first method async then in the call back execute the other method async. If you are really worried executing them sync with respect to each other.
One simple way is to use a custom threadpool
http://www.codeplex.com/smartthreadpool
You can instantiate a separate threadpool, Set the threadpool size to 1, and queue the workers

C# -Four Patterns in Asynchronous execution

I heard that there are four patterns in asynchronous execution.
There are four patterns in async delegate execution: Polling, Waiting for Completion, Completion Notification, and "Fire and Forget"
When I have the following code :
class AsynchronousDemo
{
public static int numberofFeets = 0;
public delegate long StatisticalData();
static void Main()
{
StatisticalData data = ClimbSmallHill;
IAsyncResult ar = data.BeginInvoke(null, null);
while (!ar.IsCompleted)
{
Console.WriteLine("...Climbing yet to be completed.....");
Thread.Sleep(200);
}
Console.WriteLine("..Climbing is completed...");
Console.WriteLine("... Time Taken for climbing ....{0}",
data.EndInvoke(ar).ToString()+"..Seconds");
Console.ReadKey(true);
}
static long ClimbSmallHill()
{
var sw = Stopwatch.StartNew();
while (numberofFeets <= 10000)
{
numberofFeets = numberofFeets + 100;
Thread.Sleep(10);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
}
1) What is the pattern the above code implemented ?
2) Can you explain the code ,how can i implement the rest ..?
What you have there is the Polling pattern. In this pattern you continually ask "Are we there yet?" The while loop is doing the blocking. The Thread.Sleep prevents the process from eating up CPU cycles.
Wait for Completion is the "I'll call you" approach.
IAsyncResult ar = data.BeginInvoke(null, null);
//wait until processing is done with WaitOne
//you can do other actions before this if needed
ar.AsyncWaitHandle.WaitOne();
Console.WriteLine("..Climbing is completed...");
So as soon as WaitOne is called you are blocking until climbing is complete. You can perform other tasks before blocking.
With Completion Notification you are saying "You call me, I won't call you."
IAsyncResult ar = data.BeginInvoke(Callback, null);
//Automatically gets called after climbing is complete because we specified this
//in the call to BeginInvoke
public static void Callback(IAsyncResult result) {
Console.WriteLine("..Climbing is completed...");
}
There is no blocking here because Callback is going to be notified.
And fire and forget would be
data.BeginInvoke(null, null);
//don't care about result
There is also no blocking here because you don't care when climbing is finished. As the name suggests, you forget about it. You are saying "Don't call me, I won't call you, but still, don't call me."
while (!ar.IsCompleted)
{
Console.WriteLine("...Climbing yet to be completed.....");
Thread.Sleep(200);
}
That's classic polling. - Check, sleep, check again,
This code is Polling:
while (!ar.IsCompleted)
That's the key, you keep checking whether or not it's completed.
THis code doesn't really support all four, but some code does.
Process fileProcess = new Process();
// Fill the start info
bool started = fileProcess.Start();
The "Start" method is Asynchronous. It spawns a new process.
We could do each of the ways you request with this code:
// Fire and forget
// We don't do anything, because we've started the process, and we don't care about it
// Completion Notification
fileProcess.Exited += new EventHandler(fileProcess_Exited);
// Polling
while (fileProcess.HasExited)
{
}
// Wait for completion
fileProcess.WaitForExit();

Categories

Resources