How do I avoid async void? - c#

Note: Turns out this issue is specific to Unity.
I read that async void was to be avoided. I am trying to do so using Result, but my application keeps locking up. How can I avoid using async void?
public async void PrintNumberWithAwait()
{
int number = await GetNumber();
Debug.Log(number); //Successfully prints "5"
}
public void PrintNumberWithResult()
{
int number = GetNumber().Result;
Debug.Log(number); //Application Freezes
}
private async Task<int> GetNumber()
{
await Task.Delay(1000);
return 5;
}
I thought this was correct, but I must be missing something. How do I use async/await without having async void?
I ran my tests separately with the following code (commented one out at a time):
PrintNumberWithAwait();
PrintNumberWithResult();

Short Version
Unity's Synchronization Context is single threaded. So:
Result hangs until the task completes
The task cannot complete because continuation is pushed on Main Thread, that is waiting
Detailed Version
You said you are using Unity. Unity is "99%" a single-threaded framework. So I suppose this code is executed on the Main, UI Thread.
Let's step into what your code do in details, when executing PrintNumberWithResult().
[Main Thread] From PrintNumberWithResult() you call GetNumber()
[Main Thread] You execute await Task.Delay()
[Main Thread] The code under the await line (the return 5) is "pushed" into a "List of code" to execute after that the Task (The Delay) is completed.
Small insight: This sort of list of "continuations code" is handled by a
class called SynchronizationContext (It is a c# thing, not a Unity thing). You can think this class as the guy that says HOW and WHEN the code between awaits are called. The standard .NET implementation uses a thread pool (so a set of threads) that will execute the code after the task is completed. It's like an "advanced callback". Now in Unity this is different. They implemented a custom Synchronization Context that ensures all the code is executed ALWAYS in the MAIN THREAD. We can continue now
[MAIN THREAD] The Delay Task is not completed yet, so you have an early return in the PrintNumberWithResult method, and you execute the .Result, that makes the Main Thread hangs there until the Task is completed.
[Deadlock]. 2 things are happening in this point. The Main Thread is waiting for the Task to complete. The Custom Unity's synchronization Context pushed the code above the await to be executed in the Main Thread. But The Main Thread is waiting! So it will never be free to execute that code.
Solution
Never call .Result.
If you want to fire and forget a task operation use Task.Run(() => ). But Wait! that's not a good idea in Unity! (Maybe it is in other .NET applications).
If you use Task.Run() in Unity you are forcing the async code to be executed using the default .NET Synchronization context, that uses a thread pool, and that could cause some synchronization issues if you are calling some Unity related API.
What you want to do in that case is to use an async void (not really for reasons related to exception handling), an async Task method that you will never await (better), or maybe use a library as UniTask for async await using Unity (The best in my opinion).

You misunderstood what is meant by the async void that is to be avoided.
It doesn't mean you should never use a task with no result attached. It just says the asynchronous methods that invoke them should return a Task, not void.
Simply take the signature of your async method from
public async void PrintNumberWithAwait()
and replace void with Task
public async Task PrintNumberWithAwait()
{
int number = await GetNumber();
Debug.Log(number); //Successfully prints "5"
}
Now calling methods have the option of awaiting the result, when and if they choose to. Either:
await PrintNumberWithAwait();
Or
Task t = PrintNumberWithAwait();
// Do other stuff
// ...
await t;

This answer is pretty complete and explains the "issue"/subject very well.
But to extend it a little, your example with the async void "works" for one reason: For Debug.Log the synchronization context doesn't matter. You can safely Debug.Log from different threads and background tasks and Unity handles them in the console. BUT as soon as you would try to use anything from the Unity API that is only allowed on the main thread (basically everything that immediately depends on or changes the scene content) it might break since it is not guaranteed that await ends up on the main thread.
However, what now?
Nothing really speaks against using Thread and Task.Run in Unity!
You only have to make sure to dispatch any results back into the Unity main thread.
So I just wanted to give some actual examples of how this can be done.
Something often used is a so called "Main thread dispatcher" .. basically just a ConcurrentQueue which allows you to Enqueue callback Actions from just any thread and then TryDequeue and invoke these in an Update routine on the Unity main thread.
This looks somewhat like e.g.
/// <summary>
/// A simple dispatcher behaviour for passing any multi-threading action into the next Update call in the Unity main thread
/// </summary>
public class MainThreadDispatcher : MonoBehaviour
{
/// <summary>
/// The currently existing instance of this class (singleton)
/// </summary>
private static MainThreadDispatcher _instance;
/// <summary>
/// A thread-safe queue (first-in, first-out) for dispatching actions from multiple threads into the Unity main thread
/// </summary>
private readonly ConcurrentQueue<Action> actions = new ConcurrentQueue<Action>();
/// <summary>
/// Public read-only property to access the instance
/// </summary>
public static MainThreadDispatcher Instance => _instance;
private void Awake ()
{
// Ensure singleton
if(_instance && _instance != this)
{
Destroy (gameObject);
return;
}
_instance = this;
// Keep when the scene changes
// sometimes you might not want that though
DontDestroyOnLoad (gameObject);
}
private void Update ()
{
// In the main thread work through all dispatched callbacks and invoke them
while(actions.TryDequeue(out var action))
{
action?.Invoke();
}
}
/// <summary>
/// Dispatch an action into the next <see cref="Update"/> call in the Unity main thread
/// </summary>
/// <param name="action">The action to execute in the next <see cref="Update"/> call</param>
public void DoInNextUpdate(Action action)
{
// Simply append the action thread-safe so it is scheduled for the next Update call
actions.Enqueue(action);
}
}
Of course you need this attached to an object in your scene, then from anywhere you could use e.g.
public void DoSomethingAsync()
{
// Run SomethingWrapper async and pass in a callback what to do with the result
Task.Run(async () => await SomethingWrapper(result =>
{
// since the SomethingWrapper forwards this callback to the MainThreadDispatcher
// this will be executed on the Unity main thread in the next Update frame
new GameObject(result.ToString());
}));
}
private async Task<int> Something()
{
await Task.Delay(3000);
return 42;
}
private async Task SomethingWrapper (Action<int> handleResult)
{
// cleanly await the result
var number = await Something ();
// Then dispatch given callback into the main thread
MainThreadDispatcher.Instance.DoInNextUpdate(() =>
{
handleResult?.Invoke(number);
});
}
This makes sense if you have a lot of asynchronous stuff going on and want to dispatch them all at some point back to the main thread.
Another possibility is using Coroutines. A Coroutine is basically a bit like a temporary Update method (the MoveNext of the IEnumerator is called once a frame by default) so you can just repeatedly check if your task is done already on the main thread. This is what Unity uses themselves e.g. for UnityWebRequest and could looked somewhat like
public void DoSomethingAsync()
{
// For this this needs to be a MonoBehaviour of course
StartCorouine (SomethingRoutine ());
}
private IEnumerator SomethingRoutine()
{
// Start the task async but don't wait for the result here
var task = Task.Run(Something);
// Rather wait this way
// Basically each frame check if the task is still runnning
while(!task.IsCompleted)
{
// Use the default yield which basically "pauses" the routine here
// allows Unity to execute the rest of the frame
// and continues from here in the next frame
yield return null;
}
// Safety check if the task actually finished or is canceled or faulty
if(task.IsCompletedSuccessfully)
{
// Since we already waited until the task is finished
// This time Result will not freeze the app
var number = task.Result;
new GameObject (number.ToString());
}
else
{
Debug.LogWarning("Task failed or canceled");
}
}
private async Task<int> Something ()
{
await Task.Delay(3000);
return 42;
}

Related

Wait() method of a task bloks the Task

I am working in Xamarin where I have a Task that I start at the first menupage, go through several other menupages, and then want to wait for it's completion when opening an endpage. To do this I save the task in a static field when starting it:
private static Task myTask;
public static void sync(User user)
{
if (myTask== null || myTask.IsCompleted) {
myTaskStarted = true;
//Note: do not trust on the variable being filled in immediately after the start of the task. It takes a minute. Use the flag
myTask= AsyncMyTask(user);
}
}
And then later I call a method from another page that is simply supposed to wait for myTask to finnish by calling myTask.Wait() after doing some checks on myTask having been started and not being null. But I see that once I call myTask.Wait() myTask is stuck and no longer progresses in the debugger. It's stuck. If I replace myTask.Wait() by myTask.Wait(1000) myTask is frozen for the duration of the timeout. After the timeout it continues. This is not the behaviour that is described in the documentation. Can anyone explain why the AsyncMyTask method is blocked when you call myTask.Wait() from the UI thread?
As requested: the AwaitMyTask method:
public async static Task<Boolean> AwaitMyTask()
{
if(!myTaskStarted && myTask== null)
{
return false;
} else
{
while (myTask== null)
{
Task.Delay(10);
}
}
//Stuck on the line below
myTask.Wait();
myTaskStarted = false;
return myTask.IsCompleted;
}
Task.Wait is a synchronously awaiting the task which blocks the thread. Unless you can point to a documentation stating something else, I'd say that it's expected behavior as described in https://msdn.microsoft.com/en-us/library/dd235635(v=vs.110).aspx
Wait is a synchronization method that causes the calling thread to wait until the current task has completed. ...

Should/Could this "recursive Task" be expressed as a TaskContinuation?

In my application I have the need to continually process some piece(s) of Work on some set interval(s). I had originally written a Task to continually check a given Task.Delay to see if it was completed, if so the Work would be processed that corresponded to that Task.Delay. The draw back to this method is the Task that checks these Task.Delays would be in a psuedo-infinite loop when no Task.Delay is completed.
To solve this problem I found that I could create a "recursive Task" (I am not sure what the jargon for this would be) that processes the work at the given interval as needed.
// New Recurring Work can be added by simply creating
// the Task below and adding an entry into this Dictionary.
// Recurring Work can be removed/stopped by looking
// it up in this Dictionary and calling its CTS.Cancel method.
private readonly object _LockRecurWork = new object();
private Dictionary<Work, Tuple<Task, CancellationTokenSource> RecurringWork { get; set; }
...
private Task CreateRecurringWorkTask(Work workToDo, CancellationTokenSource taskTokenSource)
{
return Task.Run(async () =>
{
// Do the Work, then wait the prescribed amount of time before doing it again
DoWork(workToDo);
await Task.Delay(workToDo.RecurRate, taskTokenSource.Token);
// If this Work's CancellationTokenSource is not
// cancelled then "schedule" the next Work execution
if (!taskTokenSource.IsCancellationRequested)
{
lock(_LockRecurWork)
{
RecurringWork[workToDo] = new Tuple<Task, CancellationTokenSource>
(CreateRecurringWorkTask(workToDo, taskTokenSource), taskTokenSource);
}
}
}, taskTokenSource.Token);
}
Should/Could this be represented with a chain of Task.ContinueWith? Would there be any benefit to such an implementation? Is there anything majorly wrong with the current implementation?
Yes!
Calling ContinueWith tells the Task to call your code as soon as it finishes. This is far faster than manually polling it.

RunAsync - How do I await the completion of work on the UI thread?

When awaiting Dispatcher.RunAsync the continuation occurs when the work is scheduled, not when the work has completed. How can I await the work completing?
Edit
My original question assumed the premature continuation was caused by the design of the API, so here's the real question.
When awaiting Dispatcher.RunAsync using an asynchronous delegate, using await within the delegate's code, the continuation occurs when the await is encountered, not when the work has completed. How can I await the work completing?
Edit 2
One reason you may need to dispatch work that's already on the UI thread is to workaround subtle timing and layout issues. It's quite common for values of sizes and positions of elements in the visual tree to be in flux and scheduling work for a later iteration of the UI can help.
I found the following suggestion on a Microsoft github repository: How to await a UI task sent from a background thread.
Setup
Define this extension method for the CoreDispatcher:
using System;
using System.Threading.Tasks;
using Windows.UI.Core;
public static class DispatcherTaskExtensions
{
public static async Task<T> RunTaskAsync<T>(this CoreDispatcher dispatcher,
Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
{
var taskCompletionSource = new TaskCompletionSource<T>();
await dispatcher.RunAsync(priority, async () =>
{
try
{
taskCompletionSource.SetResult(await func());
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
return await taskCompletionSource.Task;
}
// There is no TaskCompletionSource<void> so we use a bool that we throw away.
public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) =>
await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
}
Once you do that, all you need to do is use the new RunTaskAsync method to have your background task await on the UI work.
Usage example
Let's pretend that this is the method that needs to run in the UI thread. Pay attention to the debug statements, which will help follow the flow:
public static async Task<string> ShowMessageAsync()
{
// Set up a MessageDialog
var popup = new Windows.UI.Popups.MessageDialog("Question", "Please pick a button to continue");
popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 1"));
popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 2"));
popup.CancelCommandIndex = 0;
// About to show the dialog
Debug.WriteLine("Waiting for user choice...");
var command = await popup.ShowAsync();
// Dialog has been dismissed by the user
Debug.WriteLine("User has made a choice. Returning result.");
return command.Label;
}
To await that from your background thread, this is how you would use RunTaskAsync:
// Background thread calls this method
public async void Object_Callback()
{
Debug.WriteLine("Object_Callback() has been called.");
// Do the UI work, and await for it to complete before continuing execution
var buttonLabel = await Dispatcher.RunTaskAsync(ShowMessageAsync);
Debug.WriteLine($"Object_Callback() is running again. User clicked {buttonLabel}.");
}
The output then looks like this:
Object_Callback() has been called.
Waiting for user choice...
User has made a choice. Returning result.
Object_Callback() is running again. User clicked Button 1.
Your question is assuming that you want to schedule (and wait for) work on a UI thread from a background thread.
You'll usually find your code is much cleaner and easier to understand (and it will definitely be more portable) if you have the UI be the "master" and the background threads be the "slaves".
So, instead of having a background thread await some operation for the UI thread to do (using the awkward and unportable Dispatcher.RunAsync), you'll have the UI thread await some operation for the background thread to do (using the portable, made-for-async Task.Run).
You can wrap the call to RunAsync in your own asynchronous method that can be awaited and control the completion of the task and thus the continuation of awaiting callers yourself.
Since async-await is centred on the Task type, you must orchestrate the work using this type. However, usually a Task schedules itself to run on a threadpool thread and so it cannot be used to schedule UI work.
However, the TaskCompletionSource type was invented to act as a kind of puppeteer to an unscheduled Task. In other words, a TaskCompletionSource can create a dummy Task that is not scheduled to do anything, but via methods on the TaskCompletionSource can appear to be running and completing like a normal job.
See this example.
public Task PlayDemoAsync()
{
var completionSource = new TaskCompletionSource<bool>();
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
try
{
foreach (var ppc in this.Plots.Select(p => this.TransformPlot(p, this.RenderSize)))
{
// For each subsequent stroke plot, we need to start a new figure.
//
if (this.Sketch.DrawingPoints.Any())
this.Sketch.StartNewFigure(ppc.First().Position);
foreach (var point in ppc)
{
await Task.Delay(100);
this.Sketch.DrawingPoints.Add(point.Position);
}
}
completionSource.SetResult(true);
}
catch (Exception e)
{
completionSource.SetException(e);
}
});
return (Task)completionSource.Task;
}
Note: the main work being done on the UI thread is just some lines being drawn on screen every 100ms.
A TaskCompletionSource is created as the puppet master. Look near the end and you'll see that it has a Task property that is returned to the caller. Returning Task satisfies the compilers needs and makes the method awaitable and asynchronous.
However, the Task is just a puppet, a proxy for the actual work going on in the UI thread.
See how in that main UI delegate I use the TaskCompletionSource.SetResult method to force a result into the Task (since returned to the caller) and communicate that work has finished.
If there's an error, I use SetException to 'pull another string' and make it appear that an exception has bubbled-up in the puppet Task.
The async-await subsystem knows no different and so it works as you'd expect.
Edit
As prompted by svick, if the method was designed to be callable only from the UI thread, then this would suffice:
/// <summary>
/// Begins a demonstration drawing of the asterism.
/// </summary>
public async Task PlayDemoAsync()
{
if (this.Sketch != null)
{
foreach (var ppc in this.Plots.Select(p => this.TransformPlot(p, this.RenderSize)))
{
// For each subsequent stroke plot, we need to start a new figure.
//
if (this.Sketch.DrawingPoints.Any())
this.Sketch.StartNewFigure(ppc.First().Position);
foreach (var point in ppc)
{
await Task.Delay(100);
this.Sketch.DrawingPoints.Add(point.Position);
}
}
}
}
A nice way to work the clean way #StephenCleary suggests even if you have to start from a worker thread for some reason, is to use a simple helper object. With the object below you can write code like this:
await DispatchToUIThread.Awaiter;
// Now you're running on the UI thread, so this code is safe:
this.textBox.Text = text;
In your App.OnLaunched you have to initialize the object:
DispatchToUIThread.Initialize(rootFrame.Dispatcher);
The theory behind the code below you can find at await anything;
public class DispatchToUIThread : INotifyCompletion
{
private readonly CoreDispatcher dispatcher;
public static DispatchToUIThread Awaiter { get; private set; }
private DispatchToUIThread(CoreDispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
[CLSCompliant(false)]
public static void Initialize(CoreDispatcher dispatcher)
{
if (dispatcher == null) throw new ArgumentNullException("dispatcher");
Awaiter = new DispatchToUIThread(dispatcher);
}
public DispatchToUIThread GetAwaiter()
{
return this;
}
public bool IsCompleted
{
get { return this.dispatcher.HasThreadAccess; }
}
public async void OnCompleted(Action continuation)
{
if (continuation == null) throw new ArgumentNullException("continuation");
await this.dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => continuation());
}
public void GetResult() { }
}

What's the new C# await feature do? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Can anyone explain what the await function does?
They just talked about this at PDC yesterday!
Await is used in conjunction with Tasks (parallel programming) in .NET. It's a keyword being introduced in the next version of .NET. It more or less lets you "pause" the execution of a method to wait for the Task to complete execution. Here's a brief example:
//create and run a new task
Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation);
//run some other code immediately after this task is started and running
ShowLoaderControl();
StartStoryboard();
//this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback
// please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return
dataTask.Start();
DataTable table = await dataTask;
//Now we can perform operations on the Task result, as if we're executing code after the async operation completed
listBoxControl.DataContext = table;
StopStoryboard();
HideLoaderControl();
Basically, the async and await keywords allow you to specify that execution of a method should stop at all usages of await, which mark asynchronous method calls, and then resume once the asynchronous operation is complete. This allows you to call a method in an app's main thread and handle complex work asynchronously, without the need to explicitly define threads and joins or blocking the app's main thread.
Think of it as being somewhat similar to a yield return statement in a method producing an IEnumerable. When the runtime hits the yield, it will basically save the method's current state, and return the value or reference being yielded. The next time IEnumerator.MoveNext() is called on the return object (which is generated internally by the runtime), the method's old state is restored to the stack and execution continues with the next line after the yield return as if we'd never left the method. Without this keyword, an IEnumerator type must be custom-defined to store state and handle the iteration requests, with methods that can become VERY complex indeed.
Similarly, a method marked as async must have at least one await. On an await, the runtime will save the current thread's state and call stack, make the asynchronous call, and unwind back to the runtime's message loop to handle the next message and keep the app responsive. When the asynchronous operation is complete, at the next scheduling opportunity, the call stack to up the async operation is pushed back in and continued as if the call was synchronous.
So, these two new keywords basically simplify the coding of asynchronous processes, much like yield return simplified the generation of custom enumerables. With a couple keywords and a little background knowledge, you can skip all the confusing and often error-prone details of a traditional asynchronous pattern. This will be INVALUABLE in pretty much any event-driven GUI app like Winforms, WPF of Silverlight.
The currently accepted answer is misleading.
await is not pausing anything.
First of all it can be used only in methods or lambdas marked as async and returning Task or void if you don't care having Task instance running in this method.
Here is an illustration:
internal class Program
{
private static void Main(string[] args)
{
var task = DoWork();
Console.WriteLine("Task status: " + task.Status);
Console.WriteLine("Waiting for ENTER");
Console.ReadLine();
}
private static async Task DoWork()
{
Console.WriteLine("Entered DoWork(). Sleeping 3");
// imitating time consuming code
// in a real-world app this should be inside task,
// so method returns fast
Thread.Sleep(3000);
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("async task iteration " + i);
// imitating time consuming code
Thread.Sleep(1000);
}
});
Console.WriteLine("Exiting DoWork()");
}
}
Output:
Entered DoWork(). Sleeping 3
async task iteration 0
Task status: WaitingForActivation
Waiting for ENTER
async task iteration 1
async task iteration 2
async task iteration 3
async task iteration 4
async task iteration 5
async task iteration 6
async task iteration 7
async task iteration 8
async task iteration 9
Exiting DoWork()
For anyone new to asynchronous programming in .NET, here's a (totally fake) analogy in a scenario you may be more familiar with - AJAX calls using JavaScript/jQuery. A simple jQuery AJAX post looks like this:
$.post(url, values, function(data) {
// AJAX call completed, do something with returned data here
});
The reason we process the results in a callback function is so we don't block the current thread while waiting for the AJAX call to return. Only when the response is ready will the callback get fired, freeing the current thread to do other things in the mean time.
Now, if JavaScript supported the await keyword (which of course it doesn't (yet!)), you could achieve the same with this:
var data = await $.post(url, values);
// AJAX call completed, do something with returned data here
That's a lot cleaner, but it sure looks like we introduced synchronous, blocking code. But the (fake) JavaScript compiler would have taken everything after await and wired it into a callback, so at runtime the second example would behave just like the first.
It may not seem like it's saving you much work, but when it comes to things like exception handling and synchronization contexts, the compiler is actually doing a lot of heavy lifting for you. For more, I'd recommend the FAQs followed by Stephen Cleary's blog series.
If I had to implement it in Java it would look some thing like this:
/**
* #author Ilya Gazman
*/
public abstract class SynchronizedTask{
private ArrayList<Runnable> listeners = new ArrayList<Runnable>();
private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000));
public final void await(Runnable listener){
synchronized (this) {
listeners.add(listener);
}
}
public void excecute(){
onExcecute();
for (int i = listeners.size() - 1; i >= 0; i--) {
Runnable runnable;
synchronized (this) {
runnable = listeners.remove(i);
}
threadPoolExecutor.execute(runnable);
}
}
protected abstract void onExcecute();
}
Your application would use it like this:
public class Test{
private Job job = new Job();
public Test() {
craeteSomeJobToRunInBackground();
methode1();
methode2();
}
private void methode1(){
System.out.println("Running methode 1");
job.await(new Runnable() {
#Override
public void run() {
System.out.println("Continue to running methode 1");
}
});
}
private void methode2(){
System.out.println("Running methode 2");
}
private void craeteSomeJobToRunInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
job.excecute();
}
}).start();
}
private class Job extends SynchronizedTask{
#Override
protected void onExcecute() {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Job is done");
}
}
}

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

Categories

Resources