awaiting on an Event using IObserver Interface and AutoEventHandler/TaskCompletionSource - c#

In my scenario I am implementing an IObserver interface to poll for updates to a specific variable through a method. I have one thread that is created just to execute this method. This thread for now should never quit looking for updates to some data.
public static void findUpdates()
{
while(true)
{
CheckForUpdates(); //registered to the observer
}
}
I then have multiple threads coming into a class method to receive updates.
TaskCompletionSource<bool>updateHappened = new TaskCompletionSource<bool>();
object updatedValue;
public async Task receiveUpdates(){
while(true)
{
await updateHappened.Task;
//check to see if the thread cares about the updated value or not
//update or do not update and possibly terminate
}
}
and in the OnNext implementation
public void OnNext(Object value){
updatedHappened.SetResult(true);
}
The reason I need to await an event is because when I have threads enter my while() loop is receiveUpdates if they are not awaited then there ends up being a max number of threads that can be scheduled and some threads get blocked from executing until another exits.
This is not behaving properly right now and it I can never get past the await updateHappened.Task; line no matter how many threads I create and send through to receive updates.
I would like the ability to have threads who want to receive updates come through, suspend execution in the threadpool waiting to be executed so that other threads (however many) can also try and receive updates, and then when a update happens resume each thread one at a time and update it or not before suspending it again. The one thread will always poll for updates using the IObserver interface but every other thread trying to receive updates will always continue to look for updates unless it exits under a condition.

A TaskCompletionSource<T> can only be completed once; it's a single-shot signal, and that's it.
Since you're already using Rx, consider having the source thread expose its observable with Publish and Connect/RefCount. This will permit multiple subscribers to receive the same data. Then for the threads that just want to await, use await sequence.FirstAsync().

Related

C# Thread.Sleep()

I need somehow to bypass Thread.Sleep() method and don't get my UI Thread blocked, but I don't have to delete the method.
I need to solve the problem without deleting the Sleep method. The Sleep method simulates a delay(unresponsive application). I need to handle that.
An application is considered non-responsive when it doesn't pump its message queue. The message queue in Winforms is pumped on the GUI thread. Therefore, to make your application "responsive", you need to make sure the GUI thread has opportunities to pump the message queue - in other words, it must not run your code.
You mentioned that the Thread.Sleep simulates a "delay" in some operation you're making. However, you need to consider two main causes of such "delays":
An I/O request waiting for completion (reading a file, querying a database, sending an HTTP request...)
CPU work
The two have different solutions. If you're dealing with I/O, the best way would usually be to switch over to using asynchronous I/O. This is a breeze with await:
var response = await new HttpClient().GetAsync("http://www.google.com/");
This ensures that your GUI thread can do its job while your request is pending, and your code will restore back on the UI thread after the response gets back.
The second one is mainly solved with multi-threading. You should be extra careful when using multi-threading, because it adds in many complexities you don't get in a single-threaded model. The simplest way of treating multi-threading properly is by ensuring that you're not accessing any shared state - that's where synchronization becomes necessary. Again, with await, this is a breeze:
var someData = "Very important data";
var result = await Task.Run(() => RunComplexComputation(someData));
Again, the computation will run outside of your UI thread, but as soon as its completed and the GUI thread is idle again, your code execution will resume back on the UI thread, with the proper result.
something like that maybe ?
public async void Sleep(int milliseconds)
{
// your code
await Task.Delay(milliseconds); // non-blocking sleep
// your code
}
And if, for reasons that escape me, you HAVE to use Thread.Sleep, you can handle it like that :
public async void YourMethod()
{
// your code
await Task.Run(() => Thread.Sleep(1000)); // non-blocking sleep using Thread.Sleep
// your code
}
Use MultiThreading.
Use a different thread for sleep rather than the main GUI thread. This way it will not interfere with your Main application

Downloading strings using a Threadpool and waiting for the download to complete

I am using a WebClient to upload a string an retreive the answer from the server.
To get the job done quicker, I decided to use the ThreadPool, but I need to know when all the downloads are over.
So far, I've been using a CountdownEvent which is supposed to decrease when the server's answer has been processed.
My main thread executes this :
CountdownEvent cde = new CountdownEvent(retour["contenu"].Count()); //Set the countdown with the number of Thread that needs to be created
foreach (var tab in retour["contenu"])
{
App.AnniversaryViewModel.Items.Add(new Utilisateur(int.Parse((string)tab["id"])));
System.Diagnostics.Debug.WriteLine("Création d'un utilisateur avec l'id : " + (string)tab["id"]);
//System.Diagnostics.Debug.WriteLine("Le dernier utilisateur est : " + Items.Last<Utilisateur>().NOMPrenom);
ThreadPool.QueueUserWorkItem(App.AnniversaryViewModel.Items.Last<Utilisateur>().telechargerLesInfos , cde); //Starts the download
}
//Waiting for every Thread to be done
cde.Wait();
System.Diagnostics.Debug.WriteLine("On a fini d'attendre");
And here is, in another class, the code that is supposed to be executed by each thread :
public void telechargerLesInfos(Object cde)
{
APIWebTeam.sendRequest(RequestType.PROFIL, (Newtonsoft.Json.Linq.JObject reponse) =>
{
processInfos(reponse); //Takes the answer from the server and parse it to fill private fields
((CountdownEvent)cde).Signal();
}, "&idProfil=" + id);
}
The thing is that the delegate refuses to execute, as if the "cde.Wait()" is also forcing the thread handling the delegate to wait.
How can I fix / avoid that?
First off, the thread pool isn't really doing anything here. You're only starting an asynchronous operation in the thread pool. Starting such an operation takes basically no time at all. You may as well just do it in the main thread.
As for why the main thread is being blocked; that's easy, you're blocking the main thread yourself by waiting on the countdown event.
There is no way to have the main thread block until the async operation completes without blocking the main thread. They're literally contradictory requirements.
Instead you need to make your entire program asynchronous, to avoid blocking the main thread. Have this method take a callback that it should execute when the async operation completes, for example. The other option is to use the Task Parallel Library. Tasks make working with asynchronous operations quite a lot easier, especially if you're in a position to leverage the await keyword.

What do I do with async Tasks I don't want to wait for?

I am writing a multi player game server and am looking at ways the new C# async/await features can
help me. The core of the server is a loop which updates all the actors in the game as fast as it
can:
while (!shutdown)
{
foreach (var actor in actors)
actor.Update();
// Send and receive pending network messages
// Various other system maintenance
}
This loop is required to handle thousands of actors and update multiple times per second to keep the
game running smoothly. Some actors occasionally perform slow tasks in their update functions, such
as fetching data from a database, which is where I'd like to use async. Once this data is retrieved
the actor wants to update the game state, which must be done on the main thread.
As this is a console application, I plan to write a SynchronizationContext which can dispatch
pending delegates to the main loop. This allows those tasks to update the game once they complete
and lets unhandled exceptions be thrown into the main loop. My question is, how do write the async
update functions? This works very nicely, but breaks the recommendations not to use async void:
Thing foo;
public override void Update()
{
foo.DoThings();
if (someCondition) {
UpdateAsync();
}
}
async void UpdateAsync()
{
// Get data, but let the server continue in the mean time
var newFoo = await GetFooFromDatabase();
// Now back on the main thread, update game state
this.foo = newFoo;
}
I could make Update() async and propogate the tasks back to the main loop, but:
I don't want to add overhead to the thousands of updates that will never use it.
Even in the main loop I don't want to await the tasks and block the loop.
Awaiting the task would cause a deadlock anyway as it needs to complete on the awaiting thread.
What do I do with all these tasks I can't await? The only time I might want to know they've all
finished is when I'm shutting the server down, but I don't want to collect every task generated by
potentially weeks worth of updates.
My understanding is that the crux of it is that you want:
while (!shutdown)
{
//This should happen immediately and completions occur on the main thread.
foreach (var actor in actors)
actor.Update(); //includes i/o bound database operations
// The subsequent code should not be delayed
...
}
Where the while loop is running in your main console thread. This is a tight single-threaded loop. You could run the foreach in parallel, but then you would still be waiting for the longest running instance (the i/o bound operation to get the data from the database).
await async is not the best option within this loop, you need to run these i/o database tasks on a thread pool. On the thread pool async await would be useful to free up pool threads.
So, the next question is how to get these completions back to your main thread. Well, it seems like you need something equivalent to a message pump on your main thread. See this post for information on how to do that, though that may be a bit heavy handed. You could just have a completion queue of sorts that you check on the main thread in each pass through your while Loop. You would use one of the concurrent data structures to do this so that it is all thread safe then set Foo if it needs to be set.
It seems that there is some room to rationalise this polling of actors and threading, but without knowing the details of the app it is hard to say.
A couple of points: -
If you do not have a Wait higher up on a task, your main console thread will exit and so will your application. See here for details.
As you have pointed out, await async does not block the current thread, but it does mean that the code subsequent to the await will only execute on completion of the await.
The completion may or may not be completed on the calling thread. You have already mentioned Synchronization Context, so I won't go into the details.
Synchronization Context is null on a Console app. See here for information.
Async isn't really for fire-and-forget type operations.
For fire and forget you can use one of these options depending on your scenario:
Use Task.Run or Task.StartNew. See here for differences.
Use a producer/consumer type pattern for the long running scenarios running under your own threadpool.
Be aware of the following: -
That you will need to handle the exceptions in your spawned tasks / threads. If there are any exceptions that you do not observe, you may want to handle these, even just to log their occurence. See the information on unobserved exceptions.
If your process dies while these long running tasks are on the queue or starting they will not be run, so you may want some kind of persistence mechanism (database, external queue, file) that keeps track of the state of these operations.
If you want to know about the state of these tasks, then you will need to keep track of them in some way, whether it is an in memory list, or by querying the queues for your own thread pool or by querying the persistence mechanism. The nice thing about the persistence mechanism is that it is resilient to crashes and during shutdown you could just close down immediately, then pick up where you ended up when you restart (this of course depends on how critical it is that the tasks are run within a certain timeframe).
First, I recommend that you do not use your own SynchronizationContext; I have one available as part of my AsyncEx library that I commonly use for Console apps.
As far as your update methods go, they should return Task. My AsyncEx library has a number of "task constants" that are useful when you have a method that might be asynchronous:
public override Task Update() // Note: not "async"
{
foo.DoThings();
if (someCondition) {
return UpdateAsync();
}
else {
return TaskConstants.Completed;
}
}
async Task UpdateAsync()
{
// Get data, but let the server continue in the mean time
var newFoo = await GetFooFromDatabase();
// Now back on the main thread, update game state
this.foo = newFoo;
}
Returning to your main loop, the solution there isn't quite as clear. If you want every actor to complete before continuing to the next actor, then you can do this:
AsyncContext.Run(async () =>
{
while (!shutdown)
{
foreach (var actor in actors)
await actor.Update();
...
}
});
Alternatively, if you want to start all actors simultaneously and wait for them all to complete before moving to the next "tick", you can do this:
AsyncContext.Run(async () =>
{
while (!shutdown)
{
await Task.WhenAll(actors.Select(actor => actor.Update()));
...
}
});
When I say "simultaneously" above, it is actually starting each actor in order, and since they all execute on the main thread (including the async continuations), there's no actual simultaneous behavior; each "chuck of code" will execute on the same thread.
I highly recommend watching this video or just taking a look at the slides:
Three Essential Tips for Using Async in Microsoft Visual C# and Visual Basic
From my understanding what you should probably be doing in this scenario is returning Task<Thing> in UpdateAsync and possibly even Update.
If you are performing some async operations with 'foo' outside the main loop what happens when the async part completes during a future sequential update? I believe you really want to wait on all your update tasks to complete and then swap your internal state over in one go.
Ideally you would start all the slow (database) updates first and then do the other faster ones so that the entire set is ready as soon as possible.

How do I have the main thread wait for other threads when using the Event-based Asynchronous Pattern?

I have a main thread that starts a few worker threads through a class that implements the Event-based Asynchronous Pattern (http://msdn.microsoft.com/en-us/library/ms228969.aspx). Unfortunately, as soon as the main thread is done setting up the worker threads, it exits.
I want the main thread to wait indefinitely until the anEventHandler method is called, then process that method. The asyncevents listen for events indefinitely until canceled, so they might call the anEventHandler method multiple times before completing.
NOTE: There is no related GUI, I'm just using this pattern.
public static void Main(String[] args) {
AsyncEventClass asyncevent = new AsyncEventClass();
// setup event handling
asyncevent.Events += new EventsHandler(anEventHandler);
// start event monitoring threads
asyncevent.monitorAsync(1);
asyncevent.monitorAsync(2);
asyncevent.monitorAsync(3);
System.Console.WriteLine("The main thread now ends. :(");
}
All the examples online use System.Console.ReadLine(), but that seems like a terrible idea in production code.
You can use a simple AutoResetEvent which you wait for in the main method, and set in the event handler.
If you want to wait for a specific amount of times that the eventhandler is called, I guess you can keep a counter, and set the auto-reset-event only when you reach a certain threshold.
I ended up putting all of the IAsyncResutl objects returned by calling WorkerEventHandler.BeginInvoke into a list, and then exposing that list to the Main method. There, I setup all the asyncevents I need to listen for, then use WaitHandle.WaitAll to wait for the events to complete.

Async polling useable for GUI thread

I have read that I can use asynchronous call with polling especially when the caller thread serves the GUI. I cannot see how because:
while(AsyncResult_.IsCompleted==false) //this stops the GUI thread
{
}
So how it come it should be good for this purpose? I needed to update my GUI status bar everytime deamon thread did some progress..
You are correct in your while loop stopping the GUI thread, when doing it like that, you don't want to do that.
If you need to poll, it would be better is to set up a Timer, and check whether the work has completed when the timer fires. The Timer can have a small resolution without problems (100 ms for instance), as long as you dont do much work during each tick.
However, I think you would be even better off by using a callback, so you do not need to poll and get notified as soon as your workload is done.
The point of async polling is that you can do other things in between checking IsCompleted — such as servicing GUI events. You could set a timer, for example, to trigger an event several times per second to check whether your asynchronous operation is finished, and use the normal GUI event loop to service those events together with all the other events your GUI receives. That way, your GUI remains responsive, and shortly after the async operation finishes, your timer event handler will notice it.
I was having the same trouble with an old API exposing BeginExecute() and EndExecute(). BeginExecute() started asynchrounous operation and then went silent until it finished executing to the end. But I was needed to update intermediate state of the execution progress in real-time.
So I came up with the following solution:
var asyncResult = command.BeginExecute();
while (!asyncResult.IsCompleted)
{
if (command.State != OldState)
{
progress.Report(newState);
}
// Key piece in this polling loop.
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
}
command.EndExecute(asyncResult);
At first I have used
await Task.Yield();
But then I found out that in WPF it won't return the control to GUI, because this loop will have higher priority. That is why I switched to this instruction:
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
So now GUI will check and update progress only when it has nothing else to do :)

Categories

Resources