patterncsharpMinor
Stopping a long-running asynchronous computation
Viewed 0 times
computationstoppingasynchronouslongrunning
Problem
I'm writing a program that will perform a long-running computation, gradually improving a solution. On top of that, there's a simple UI that basically allows the user to stop the computation (letting the worker finish a step it's working on) and shows the best solution.
Here's a simplified version of what I have, I'm using async/await for the first time. Is there anything you would improve, or any other comments?
Worker code
UI
Here's a simplified version of what I have, I'm using async/await for the first time. Is there anything you would improve, or any other comments?
Worker code
public class SearchEngine
{
//...
public async Task Search(CancellationTokenSource cts)
{
await Task.Factory.StartNew(() => {
BestSolution = Problem.RandomSolution();
while (!cts.IsCancellationRequested)
{
IProblemSolution s = Problem.RandomSolution(); // for simplification
if (s.ObjectiveValue() < BestSolution.ObjectiveValue())
BestSolution = s;
}
});
return BestSolution;
}
}UI
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
if (CancelTokenSrc != null)
return;
CancelTokenSrc = new CancellationTokenSource();
Engine = new SearchEngine(new SampleProblem());
StopButton.IsEnabled = true;
StartButton.IsEnabled = false;
Task t = Engine.Search(CancelTokenSrc);
await t;
ResultLabel.Content = t.Result.ObjectiveValue().ToString();
StopButton.IsEnabled = false;
StartButton.IsEnabled = true;
CancelTokenSrc = null;
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
if (CancelTokenSrc != null)
CancelTokenSrc.Cancel();
}Solution
Task-based Asynchronous Pattern (MSDN)
As I explain in this answer, one would rightfully expect the signature of that method to read like this:
The pattern for
I haven't written much
Could be written like this:
My understanding is that
Other than that, I find you could give
To this:
Lastly, I might be biased because I use ReSharper and with that tool IntelliSense/auto-complete is much "smarter", but I don't like names like
public async Task Search(CancellationTokenSource cts)As I explain in this answer, one would rightfully expect the signature of that method to read like this:
public async Task SearchAsync(CancellationTokenSource cts)The pattern for
async methods is quite simple: use the async keyword, return Task or Task, and put an "Async" suffix to the method's name.I haven't written much
async code (read: never wrote a line of C# that leverages features of .net 4.5), but from previous reviews of such code I think this:Task t = Engine.Search(CancelTokenSrc);
await t;
ResultLabel.Content = t.Result.ObjectiveValue().ToString();Could be written like this:
var searchResult = await Engine.SearchAsync(CancelTokenSrc);
ResultLabel.Content = searchResult.ObjectiveValue().ToString();
//...My understanding is that
await somehow deals with Task.Result and so the type of searchResult would be IProblemSolution - I might be wrong here though.Other than that, I find you could give
var some lovin', and change this:IProblemSolution s = Problem.RandomSolution();To this:
var s = Problem.RandomSolution();Lastly, I might be biased because I use ReSharper and with that tool IntelliSense/auto-complete is much "smarter", but I don't like names like
cts - I'd rather call it cancelTokenSource and then I can type ctsTab and poof I'm referring to a readable identifier with a pronounceable name.Code Snippets
public async Task<IProblemSolution> Search(CancellationTokenSource cts)public async Task<IProblemSolution> SearchAsync(CancellationTokenSource cts)Task<IProblemSolution> t = Engine.Search(CancelTokenSrc);
await t;
ResultLabel.Content = t.Result.ObjectiveValue().ToString();var searchResult = await Engine.SearchAsync(CancelTokenSrc);
ResultLabel.Content = searchResult.ObjectiveValue().ToString();
//...IProblemSolution s = Problem.RandomSolution();Context
StackExchange Code Review Q#45838, answer score: 2
Revisions (0)
No revisions yet.