using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Text; using System.Threading; using System.Windows.Forms; namespace AsyncCalcPiWithBackgroundWorkerSample { partial class AsyncCalcPiForm : Form { public AsyncCalcPiForm() { InitializeComponent(); } void ShowProgress(string pi, int totalDigits, int digitsSoFar) { // Make sure we're on the UI thread Debug.Assert(this.InvokeRequired == false); // Display progress in UI this.resultsTextBox.Text = pi; this.calcToolStripProgressBar.Maximum = totalDigits; this.calcToolStripProgressBar.Value = digitsSoFar; // No need to check for digitsSoFar == totalDigits //if( digitsSoFar == totalDigits ) { // // Reset UI // this.calcToolStripStatusLabel.Text = "Ready"; // this.calcToolStripProgressBar.Visible = false; //} } //delegate void ShowProgressDelegate( // string pi, int totalDigits, int digitsSoFar); class CalcPiUserState { public readonly string Pi; public readonly int TotalDigits; public readonly int DigitsSoFar; public CalcPiUserState(string pi, int totalDigits, int digitsSoFar) { this.Pi = pi; this.TotalDigits = totalDigits; this.DigitsSoFar = digitsSoFar; } } void CalcPi(int digits) { StringBuilder pi = new StringBuilder("3", digits + 2); //// Get ready to show progress //ShowProgressDelegate showProgress = // new ShowProgressDelegate(ShowProgress); // Show initial progress asynchronously //this.BeginInvoke( // showProgress, // new object[] { pi.ToString(), digits, 0 }); // Report initial progress this.backgroundWorker.ReportProgress(0, new CalcPiUserState(pi.ToString(), digits, 0)); if( digits > 0 ) { pi.Append("."); for( int i = 0; i < digits; i += 9 ) { int nineDigits = NineDigitsOfPi.StartingAt(i + 1); int digitCount = Math.Min(digits - i, 9); string ds = string.Format("{0:D9}", nineDigits); pi.Append(ds.Substring(0, digitCount)); // Show continuing progress asynchronously //this.BeginInvoke( // showProgress, // new object[] { pi.ToString(), digits, i + digitCount }); // Report continuing progress this.backgroundWorker.ReportProgress(0, new CalcPiUserState(pi.ToString(), digits, i + digitCount)); } } } //delegate void CalcPiDelegate(int digits); void calcButton_Click(object sender, EventArgs e) { // Set calculating UI this.calcToolStripProgressBar.Visible = true; this.calcToolStripStatusLabel.Text = "Calculating..."; // Begin calculating pi asynchronously //CalcPiDelegate calcPi = new CalcPiDelegate(CalcPi); //calcPi.BeginInvoke( // (int)this.decimalPlacesNumericUpDown.Value, // CalcPi argument // EndCalcPi, // Called when CalcPi completes // calcPi); // EndCalcPi argument (indirectly) // Begin calculating pi asynchronously this.backgroundWorker.RunWorkerAsync( (int)this.decimalPlacesNumericUpDown.Value); } //void EndCalcPi(IAsyncResult ar) { // // Harvest results, re-thrown exceptions and clean-up resources // try { // CalcPiDelegate calcPi = (CalcPiDelegate)ar.AsyncState; // calcPi.EndInvoke(ar); // } // catch( Exception ex ) { // // Show error // ShowProgressDelegate showProgress = // new ShowProgressDelegate(ShowProgress); // this.BeginInvoke( // showProgress, // new object[] { ex.Message, 0, 0 }); // } //} void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { //throw new Exception("Oops"); // Track start time DateTime start = DateTime.Now; CalcPi((int)e.Argument); // Return elapsed time DateTime end = DateTime.Now; TimeSpan elapsed = end - start; e.Result = elapsed; } void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { // Show progress CalcPiUserState progress = (CalcPiUserState)e.UserState; ShowProgress( progress.Pi, progress.TotalDigits, progress.DigitsSoFar); } void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // Reset progress UI this.calcToolStripStatusLabel.Text = "Ready"; this.calcToolStripProgressBar.Visible = false; // Was there an error? if( e.Error != null ) { this.resultsTextBox.Text = e.Error.Message; return; } // Show elapsed time TimeSpan elapsed = (TimeSpan)e.Result; MessageBox.Show("Elapsed: " + elapsed.ToString()); } } }