I am just about to embark upon a massive job of multi-threading a cost-engine. I could use TPL of which I am very familiar, but would like to leverage the async
/await
keywords of .NET 4.5 to make life that little bit simpler.
Is my understanding of what is going on correct? How can I improve this design?
CancellationTokenSource cancelSource;
// Mark the event handler with async so you can use await in it.
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
cancelSource = new CancellationTokenSource();
CancellationToken token = cancelSource.Token;
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
IProgress<ProgressInfo> progressInfo = new Progress<ProgressInfo>(ReportProgress);
await ProcessScript(progressInfo, token, uiScheduler);
// await sets up the following as an Contnuation to
// continue once returned from await.
this.resultsTextBox.AppendText("\nReturn to caller...\n\n");
}
// Class to report progress...
private void ReportProgress(ProgressInfo progressInfo)
{
this.progressBar.Value = progressInfo.PrecentComplete;
this.progressLabel.Content = progressInfo.Message;
}
private async Task ProcessScript(IProgress<ProgressInfo> progressInfo,
CancellationToken token,
TaskScheduler uiScheduler)
{
ProgressInfo pi = new ProgressInfo();
pi.PrecentComplete = 0;
pi.Message = "In script processor...";
progressInfo.Report(pi);
Thread.Sleep(5000); // This is UI Blocking...
string str = this.resultsTextBox.Text;
str = "We have added this => going into await...";
this.resultsTextBox.AppendText(str);
Task task = Task.Factory.StartNew(() => LongRunning(uiScheduler));
pi.Message = "Task set";
pi.PrecentComplete = 50;
progressInfo.Report(pi);
// awaits the long runniing task - non-UI blocking.
await task;
// The await above sets this up as a continuation on the UI thread.
pi.Message = "Task awaited";
pi.PrecentComplete = 95;
progressInfo.Report(pi);
this.resultsTextBox.AppendText("Where are we now??");
return;
}
private bool LongRunning(TaskScheduler uiScheduler)
{
// Allow access to the UI from this background thread from
// the ThreadPool.
Task.Factory.StartNew(() =>
{
this.resultsTextBox.AppendText("\n\nNow in 'LongRunning'!! Waiting 5s simulating HARD WORK!!");
}, CancellationToken.None,
TaskCreationOptions.None,
uiScheduler);
// Simulate hard work.
Thread.Sleep(7000);
Task.Factory.StartNew(() =>
{
this.resultsTextBox.AppendText("\n\n\nHARD WORK COMPLETE!!");
}, CancellationToken.None,
TaskCreationOptions.None,
uiScheduler);
return true;
}
async
/await
code", for instance, would be a better fit. \$\endgroup\$