Asynchronous call by synchronous method

Here is a simple example:

public event EventHandler CookinDone = delegate{}; public void CoockinRequest(){ var indicator = new ActivityIndicator(); ActivityIndicator.Show("Oooo coockin' something cool"); var bw = new BackgroundWorker(); bw.DoWork += (sender, e) => CockinService.Cook(); bw.RunWorkerCompleted += (sender, e) => { indicator.Hide(); CookinDone.Invoke(this,null); }; bw.RunWorkerAsync(); } 

Now, every time I use this method, I have to catch the CookinDone event and move on.

 var cook = new Cook(); cook.CookinDone += (sender, e) => MessageBox.Show("Yay, smells good"); cook.CoockinRequest(); 

But how can I simplify this by making the return type of the method as Boolean and returning the result after the Cookin finishes?

 if (CoockinRequest()) MessageBox.Show('Yay, smells even better'); 

If I put something like while (bw.IsBusy) , it will close my ActivityIndicator, freeze the main thread, and I feel that this would be the worst thing. There are also some Monitor.Wait things and some other things like TaskFactory , but it all seems too complicated to use in simple scripts.

It may be different in different environments, for example, some approach is good for WPF applications, some for something else and something else, but there must be a common template is not it?

How do you do this?

+6
source share
1 answer

There is no direct way to do this in .NET. This is actually very similar to the new async / await functionality coming in the next version of C #.

A parallel task library can be used in .NET 4 to achieve this goal today. You would do this by modifying your code to return a Task<bool> so that the caller can wait (if necessary) or sign up to continue the task that will be executed when it is completed.

To do this, you must rewrite the above code like this:

 public Task<bool> CoockinRequestAsync() { var indicator = new ActivityIndicator(); ActivityIndicator.Show("Oooo coockin' something cool"); // This assumes Cook() returns bool... var task = Task.Factory.StartNew(CockinService.Cook); // Handle your removal of the indicator here.... task.ContinueWith( (t) => { indicator.Hide(); }, TaskScheduler.FromCurrentSynchronizationContext()); // Return the task so the caller can schedule their own completions return task; } 

Then, when you go to use this, you should write something like:

 private void SomeMethod() { var request = this.CoockinRequestAsync(); request.ContinueWith( t => { // This will run when the request completes... bool result = t.Result; // Use result as needed here, ie: update your UI }, TaskScheduler.FromCurrentSynchronizationContext()); } 
+7
source

Source: https://habr.com/ru/post/899736/


All Articles