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

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.

Related

Cancel Tasks in c# [duplicate]

We could abort a Thread like this:
Thread thread = new Thread(SomeMethod);
.
.
.
thread.Abort();
But can I abort a Task (in .Net 4.0) in the same way not by cancellation mechanism. I want to kill the Task immediately.
The guidance on not using a thread abort is controversial. I think there is still a place for it but in exceptional circumstance. However you should always attempt to design around it and see it as a last resort.
Example;
You have a simple windows form application that connects to a blocking synchronous web service. Within which it executes a function on the web service within a Parallel loop.
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Parallel.ForEach(iListOfItems, po, (item, loopState) =>
{
Thread.Sleep(120000); // pretend web service call
});
Say in this example, the blocking call takes 2 mins to complete. Now I set my MaxDegreeOfParallelism to say ProcessorCount. iListOfItems has 1000 items within it to process.
The user clicks the process button and the loop commences, we have 'up-to' 20 threads executing against 1000 items in the iListOfItems collection. Each iteration executes on its own thread. Each thread will utilise a foreground thread when created by Parallel.ForEach. This means regardless of the main application shutdown, the app domain will be kept alive until all threads have finished.
However the user needs to close the application for some reason, say they close the form.
These 20 threads will continue to execute until all 1000 items are processed. This is not ideal in this scenario, as the application will not exit as the user expects and will continue to run behind the scenes, as can be seen by taking a look in task manger.
Say the user tries to rebuild the app again (VS 2010), it reports the exe is locked, then they would have to go into task manager to kill it or just wait until all 1000 items are processed.
I would not blame you for saying, but of course! I should be cancelling these threads using the CancellationTokenSource object and calling Cancel ... but there are some problems with this as of .net 4.0. Firstly this is still never going to result in a thread abort which would offer up an abort exception followed by thread termination, so the app domain will instead need to wait for the threads to finish normally, and this means waiting for the last blocking call, which would be the very last running iteration (thread) that ultimately gets to call po.CancellationToken.ThrowIfCancellationRequested.
In the example this would mean the app domain could still stay alive for up to 2 mins, even though the form has been closed and cancel called.
Note that Calling Cancel on CancellationTokenSource does not throw an exception on the processing thread(s), which would indeed act to interrupt the blocking call similar to a thread abort and stop the execution. An exception is cached ready for when all the other threads (concurrent iterations) eventually finish and return, the exception is thrown in the initiating thread (where the loop is declared).
I chose not to use the Cancel option on a CancellationTokenSource object. This is wasteful and arguably violates the well known anti-patten of controlling the flow of the code by Exceptions.
Instead, it is arguably 'better' to implement a simple thread safe property i.e. Bool stopExecuting. Then within the loop, check the value of stopExecuting and if the value is set to true by the external influence, we can take an alternate path to close down gracefully. Since we should not call cancel, this precludes checking CancellationTokenSource.IsCancellationRequested which would otherwise be another option.
Something like the following if condition would be appropriate within the loop;
if (loopState.ShouldExitCurrentIteration || loopState.IsExceptional || stopExecuting) {loopState.Stop(); return;}
The iteration will now exit in a 'controlled' manner as well as terminating further iterations, but as I said, this does little for our issue of having to wait on the long running and blocking call(s) that are made within each iteration (parallel loop thread), since these have to complete before each thread can get to the option of checking if it should stop.
In summary, as the user closes the form, the 20 threads will be signaled to stop via stopExecuting, but they will only stop when they have finished executing their long running function call.
We can't do anything about the fact that the application domain will always stay alive and only be released when all foreground threads have completed. And this means there will be a delay associated with waiting for any blocking calls made within the loop to complete.
Only a true thread abort can interrupt the blocking call, and you must mitigate leaving the system in a unstable/undefined state the best you can in the aborted thread's exception handler which goes without question. Whether that's appropriate is a matter for the programmer to decide, based on what resource handles they chose to maintain and how easy it is to close them in a thread's finally block. You could register with a token to terminate on cancel as a semi workaround i.e.
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Parallel.ForEach(iListOfItems, po, (item, loopState) =>
{
using (cts.Token.Register(Thread.CurrentThread.Abort))
{
Try
{
Thread.Sleep(120000); // pretend web service call
}
Catch(ThreadAbortException ex)
{
// log etc.
}
Finally
{
// clean up here
}
}
});
but this will still result in an exception in the declaring thread.
All things considered, interrupt blocking calls using the parallel.loop constructs could have been a method on the options, avoiding the use of more obscure parts of the library. But why there is no option to cancel and avoid throwing an exception in the declaring method strikes me as a possible oversight.
But can I abort a Task (in .Net 4.0) in the same way not by
cancellation mechanism. I want to kill the Task immediately.
Other answerers have told you not to do it. But yes, you can do it. You can supply Thread.Abort() as the delegate to be called by the Task's cancellation mechanism. Here is how you could configure this:
class HardAborter
{
public bool WasAborted { get; private set; }
private CancellationTokenSource Canceller { get; set; }
private Task<object> Worker { get; set; }
public void Start(Func<object> DoFunc)
{
WasAborted = false;
// start a task with a means to do a hard abort (unsafe!)
Canceller = new CancellationTokenSource();
Worker = Task.Factory.StartNew(() =>
{
try
{
// specify this thread's Abort() as the cancel delegate
using (Canceller.Token.Register(Thread.CurrentThread.Abort))
{
return DoFunc();
}
}
catch (ThreadAbortException)
{
WasAborted = true;
return false;
}
}, Canceller.Token);
}
public void Abort()
{
Canceller.Cancel();
}
}
disclaimer: don't do this.
Here is an example of what not to do:
var doNotDoThis = new HardAborter();
// start a thread writing to the console
doNotDoThis.Start(() =>
{
while (true)
{
Thread.Sleep(100);
Console.Write(".");
}
return null;
});
// wait a second to see some output and show the WasAborted value as false
Thread.Sleep(1000);
Console.WriteLine("WasAborted: " + doNotDoThis.WasAborted);
// wait another second, abort, and print the time
Thread.Sleep(1000);
doNotDoThis.Abort();
Console.WriteLine("Abort triggered at " + DateTime.Now);
// wait until the abort finishes and print the time
while (!doNotDoThis.WasAborted) { Thread.CurrentThread.Join(0); }
Console.WriteLine("WasAborted: " + doNotDoThis.WasAborted + " at " + DateTime.Now);
Console.ReadKey();
You shouldn't use Thread.Abort()
Tasks can be Cancelled but not aborted.
The Thread.Abort() method is (severely) deprecated.
Both Threads and Tasks should cooperate when being stopped, otherwise you run the risk of leaving the system in a unstable/undefined state.
If you do need to run a Process and kill it from the outside, the only safe option is to run it in a separate AppDomain.
This answer is about .net 3.5 and earlier.
Thread-abort handling has been improved since then, a.o. by changing the way finally blocks work.
But Thread.Abort is still a suspect solution that you should always try to avoid.
And in .net Core (.net 5+) Thread.Abort() will now throw a PlatformNotSupportedException .
Kind of underscoring the 'deprecated' point.
Everyone knows (hopefully) its bad to terminate thread. The problem is when you don't own a piece of code you're calling. If this code is running in some do/while infinite loop , itself calling some native functions, etc. you're basically stuck. When this happens in your own code termination, stop or Dispose call, it's kinda ok to start shooting the bad guys (so you don't become a bad guy yourself).
So, for what it's worth, I've written those two blocking functions that use their own native thread, not a thread from the pool or some thread created by the CLR. They will stop the thread if a timeout occurs:
// returns true if the call went to completion successfully, false otherwise
public static bool RunWithAbort(this Action action, int milliseconds) => RunWithAbort(action, new TimeSpan(0, 0, 0, 0, milliseconds));
public static bool RunWithAbort(this Action action, TimeSpan delay)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var source = new CancellationTokenSource(delay);
var success = false;
var handle = IntPtr.Zero;
var fn = new Action(() =>
{
using (source.Token.Register(() => TerminateThread(handle, 0)))
{
action();
success = true;
}
});
handle = CreateThread(IntPtr.Zero, IntPtr.Zero, fn, IntPtr.Zero, 0, out var id);
WaitForSingleObject(handle, 100 + (int)delay.TotalMilliseconds);
CloseHandle(handle);
return success;
}
// returns what's the function should return if the call went to completion successfully, default(T) otherwise
public static T RunWithAbort<T>(this Func<T> func, int milliseconds) => RunWithAbort(func, new TimeSpan(0, 0, 0, 0, milliseconds));
public static T RunWithAbort<T>(this Func<T> func, TimeSpan delay)
{
if (func == null)
throw new ArgumentNullException(nameof(func));
var source = new CancellationTokenSource(delay);
var item = default(T);
var handle = IntPtr.Zero;
var fn = new Action(() =>
{
using (source.Token.Register(() => TerminateThread(handle, 0)))
{
item = func();
}
});
handle = CreateThread(IntPtr.Zero, IntPtr.Zero, fn, IntPtr.Zero, 0, out var id);
WaitForSingleObject(handle, 100 + (int)delay.TotalMilliseconds);
CloseHandle(handle);
return item;
}
[DllImport("kernel32")]
private static extern bool TerminateThread(IntPtr hThread, int dwExitCode);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(IntPtr lpThreadAttributes, IntPtr dwStackSize, Delegate lpStartAddress, IntPtr lpParameter, int dwCreationFlags, out int lpThreadId);
[DllImport("kernel32")]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32")]
private static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
While it's possible to abort a thread, in practice it's almost always a very bad idea to do so. Aborthing a thread means the thread is not given a chance to clean up after itself, leaving resources undeleted, and things in unknown states.
In practice, if you abort a thread, you should only do so in conjunction with killing the process. Sadly, all too many people think ThreadAbort is a viable way of stopping something and continuing on, it's not.
Since Tasks run as threads, you can call ThreadAbort on them, but as with generic threads you almost never want to do this, except as a last resort.
I faced a similar problem with Excel's Application.Workbooks.
If the application is busy, the method hangs eternally. My approach was simply to try to get it in a task and wait, if it takes too long, I just leave the task be and go away (there is no harm "in this case", Excel will unfreeze the moment the user finishes whatever is busy).
In this case, it's impossible to use a cancellation token. The advantage is that I don't need excessive code, aborting threads, etc.
public static List<Workbook> GetAllOpenWorkbooks()
{
//gets all open Excel applications
List<Application> applications = GetAllOpenApplications();
//this is what we want to get from the third party library that may freeze
List<Workbook> books = null;
//as Excel may freeze here due to being busy, we try to get the workbooks asynchronously
Task task = Task.Run(() =>
{
try
{
books = applications
.SelectMany(app => app.Workbooks.OfType<Workbook>()).ToList();
}
catch { }
});
//wait for task completion
task.Wait(5000);
return books; //handle outside if books is null
}
This is my implementation of an idea presented by #Simon-Mourier, using the dotnet thread, short and simple code:
public static bool RunWithAbort(this Action action, int milliseconds)
{
if (action == null) throw new ArgumentNullException(nameof(action));
var success = false;
var thread = new Thread(() =>
{
action();
success = true;
});
thread.IsBackground = true;
thread.Start();
thread.Join(milliseconds);
thread.Abort();
return success;
}
You can "abort" a task by running it on a thread you control and aborting that thread. This causes the task to complete in a faulted state with a ThreadAbortException. You can control thread creation with a custom task scheduler, as described in this answer. Note that the caveat about aborting a thread applies.
(If you don't ensure the task is created on its own thread, aborting it would abort either a thread-pool thread or the thread initiating the task, neither of which you typically want to do.)
using System;
using System.Threading;
using System.Threading.Tasks;
...
var cts = new CancellationTokenSource();
var task = Task.Run(() => { while (true) { } });
Parallel.Invoke(() =>
{
task.Wait(cts.Token);
}, () =>
{
Thread.Sleep(1000);
cts.Cancel();
});
This is a simple snippet to abort a never-ending task with CancellationTokenSource.

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

IAsyncResult.AsyncWaitHandle.WaitOne() completes ahead of callback

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;
}

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