I have a rather complicated WPF application that (like VS2013) has IDocuments and ITools fixed in the main shell of the application. One of these Tools should be safely disabled when the main window is closed to avoid getting into a “bad” state. Therefore, I use the Caliburn Micro public override void CanClose(Action<bool> callback) to perform some database updates, etc. The problem I have is all the update code in this method using MongoDB Driver 2.0, and this async stuff. Some code; I'm currently trying to execute
public override void CanClose(Action<bool> callback) { if (BackTestCollection.Any(bt => bt.TestStatus == TestStatus.Running)) { using (ManualResetEventSlim tareDownCompleted = new ManualResetEventSlim(false)) { // Update running test. Task.Run(async () => { StatusMessage = "Stopping running backtest..."; await SaveBackTestEventsAsync(SelectedBackTest); Log.Trace(String.Format( "Shutdown requested: saved backtest \"{0}\" with events", SelectedBackTest.Name)); this.source = new CancellationTokenSource(); this.token = this.source.Token; var filter = Builders<BsonDocument>.Filter.Eq( BackTestFields.ID, DocIdSerializer.Write(SelectedBackTest.Id)); var update = Builders<BsonDocument>.Update.Set(BackTestFields.STATUS, TestStatus.Cancelled); IMongoDatabase database = client.GetDatabase(Constants.DatabaseMappings[Database.Backtests]); await MongoDataService.UpdateAsync<BsonDocument>( database, Constants.Backtests, filter, update, token); Log.Trace(String.Format( "Shutdown requested: updated backtest \"{0}\" status to \"Cancelled\"", SelectedBackTest.Name)); }).ContinueWith(ant => { StatusMessage = "Disposing backtest engine..."; if (engine != null) engine.Dispose(); Log.Trace("Shutdown requested: disposed backtest engine successfully"); callback(true); tareDownCompleted.Set(); }); tareDownCompleted.Wait(); } } }
Now, to start with the fact that I did not have ManualResetEventSlim , and this will obviously return to the calling CanClose before I update my database in the background thread [pool-pool]. In an attempt to prevent the return until I finish my updates, I tried to block the return, but this freezes the UI thread and prevents anything.
How can I run my clearing code without returning to the caller too soon?
Thank you for your time.
Please note: I cannot override the OnClose method using asynchronous signature, because the call code does not wait for it (I can not control this).
c # asynchronous semaphore task blocking
Moonknight
source share