Background Worker Pattern
代码
1using System;
2using System.Threading;
3using System.ComponentModel;
4using System.Text;
5
6public class PiCalculator
7{
8 public static BackgroundWorker calculationWorker = new BackgroundWorker();
9 public static AutoResetEvent resetEvent = new AutoResetEvent(false);
10
11 public static void Main()
12 {
13 int digitCount;
14
15 Console.Write("Enter the number of digits to calculate:");
16
17 if (int.TryParse(Console.ReadLine(), out digitCount))
18 {
19 Console.WriteLine("ENTER to cancel");
20 // C# 2.0 Syntax for registering delegates
21 calculationWorker.DoWork += CalculatePi;
22 // Register the ProgressChanged callback
23 calculationWorker.ProgressChanged +=
24 UpdateDisplayWithMoreDigits;
25 calculationWorker.WorkerReportsProgress = true;
26 // Register a callback for when the
27 // calculation completes
28 calculationWorker.RunWorkerCompleted +=
29 new RunWorkerCompletedEventHandler(Complete);
30 calculationWorker.WorkerSupportsCancellation = true;
31
32 // Begin calculating pi for up to digitCount digits
33 calculationWorker.RunWorkerAsync(digitCount);
34
35 Console.ReadLine();
36 // If cancel is called after the calculation
37 // has completed it doesn't matter.
38 calculationWorker.CancelAsync();
39 // Wait for Complete() to run.
40 resetEvent.WaitOne();
41 }
42 else
43 {
44 Console.WriteLine(
45 "The value entered is an invalid integer.");
46 }
47 }
48
49 private static void CalculatePi(object sender, DoWorkEventArgs eventArgs)
50 {
51 int digits = (int)eventArgs.Argument;
52
53 StringBuilder pi = new StringBuilder("3.", digits + 2);
54 calculationWorker.ReportProgress(0, pi.ToString());
55
56 // Calculate rest of pi, if required
57 if (digits > 0)
58 {
59 for (int i = 0; i < digits; i += 9)
60 {
61
62
63 // Calculate next i decimal places
64 int nextDigit = PiDigitCalculator.StartingAt(
65 i + 1);
66 int digitCount = Math.Min(digits - i, 9);
67 string ds = string.Format("{0:D9}", nextDigit);
68 pi.Append(ds.Substring(0, digitCount));
69
70 // Show current progress
71 calculationWorker.ReportProgress(
72 0, ds.Substring(0, digitCount));
73
74 // Check for cancellation
75 if (calculationWorker.CancellationPending)
76 {
77 // Need to set Cancel if you need to
78 // distinguish how a worker thread completed
79 // i.e., by checking
80 // RunWorkerCompletedEventArgs.Cancelled
81 eventArgs.Cancel = true;
82 break;
83 }
84 }
85 }
86 eventArgs.Result = pi.ToString();
87 }
88
89 private static void UpdateDisplayWithMoreDigits(object sender, ProgressChangedEventArgs eventArgs)
90 {
91 string digits = (string)eventArgs.UserState;
92
93 Console.Write(digits);
94
95 }
96
97 static void Complete(object sender, RunWorkerCompletedEventArgs eventArgs)
98 {
99 Console.WriteLine();
100 if (eventArgs.Cancelled)
101 {
102 Console.WriteLine("Cancelled");
103 }
104 else if (eventArgs.Error != null)
105 {
106 // IMPORTANT: check error to retrieve any exceptions.
107 Console.WriteLine(
108 "ERROR: {0}", eventArgs.Error.Message);
109 }
110 else
111 {
112 Console.WriteLine("Finished");
113 }
114 resetEvent.Set();
115
116 }
117}
118
119public class PiDigitCalculator
120{
121 //
122 public static int StartingAt(int i)
123 {
124 Thread.Sleep(1000);
125 return i;
126 }
127}
1using System;
2using System.Threading;
3using System.ComponentModel;
4using System.Text;
5
6public class PiCalculator
7{
8 public static BackgroundWorker calculationWorker = new BackgroundWorker();
9 public static AutoResetEvent resetEvent = new AutoResetEvent(false);
10
11 public static void Main()
12 {
13 int digitCount;
14
15 Console.Write("Enter the number of digits to calculate:");
16
17 if (int.TryParse(Console.ReadLine(), out digitCount))
18 {
19 Console.WriteLine("ENTER to cancel");
20 // C# 2.0 Syntax for registering delegates
21 calculationWorker.DoWork += CalculatePi;
22 // Register the ProgressChanged callback
23 calculationWorker.ProgressChanged +=
24 UpdateDisplayWithMoreDigits;
25 calculationWorker.WorkerReportsProgress = true;
26 // Register a callback for when the
27 // calculation completes
28 calculationWorker.RunWorkerCompleted +=
29 new RunWorkerCompletedEventHandler(Complete);
30 calculationWorker.WorkerSupportsCancellation = true;
31
32 // Begin calculating pi for up to digitCount digits
33 calculationWorker.RunWorkerAsync(digitCount);
34
35 Console.ReadLine();
36 // If cancel is called after the calculation
37 // has completed it doesn't matter.
38 calculationWorker.CancelAsync();
39 // Wait for Complete() to run.
40 resetEvent.WaitOne();
41 }
42 else
43 {
44 Console.WriteLine(
45 "The value entered is an invalid integer.");
46 }
47 }
48
49 private static void CalculatePi(object sender, DoWorkEventArgs eventArgs)
50 {
51 int digits = (int)eventArgs.Argument;
52
53 StringBuilder pi = new StringBuilder("3.", digits + 2);
54 calculationWorker.ReportProgress(0, pi.ToString());
55
56 // Calculate rest of pi, if required
57 if (digits > 0)
58 {
59 for (int i = 0; i < digits; i += 9)
60 {
61
62
63 // Calculate next i decimal places
64 int nextDigit = PiDigitCalculator.StartingAt(
65 i + 1);
66 int digitCount = Math.Min(digits - i, 9);
67 string ds = string.Format("{0:D9}", nextDigit);
68 pi.Append(ds.Substring(0, digitCount));
69
70 // Show current progress
71 calculationWorker.ReportProgress(
72 0, ds.Substring(0, digitCount));
73
74 // Check for cancellation
75 if (calculationWorker.CancellationPending)
76 {
77 // Need to set Cancel if you need to
78 // distinguish how a worker thread completed
79 // i.e., by checking
80 // RunWorkerCompletedEventArgs.Cancelled
81 eventArgs.Cancel = true;
82 break;
83 }
84 }
85 }
86 eventArgs.Result = pi.ToString();
87 }
88
89 private static void UpdateDisplayWithMoreDigits(object sender, ProgressChangedEventArgs eventArgs)
90 {
91 string digits = (string)eventArgs.UserState;
92
93 Console.Write(digits);
94
95 }
96
97 static void Complete(object sender, RunWorkerCompletedEventArgs eventArgs)
98 {
99 Console.WriteLine();
100 if (eventArgs.Cancelled)
101 {
102 Console.WriteLine("Cancelled");
103 }
104 else if (eventArgs.Error != null)
105 {
106 // IMPORTANT: check error to retrieve any exceptions.
107 Console.WriteLine(
108 "ERROR: {0}", eventArgs.Error.Message);
109 }
110 else
111 {
112 Console.WriteLine("Finished");
113 }
114 resetEvent.Set();
115
116 }
117}
118
119public class PiDigitCalculator
120{
121 //
122 public static int StartingAt(int i)
123 {
124 Thread.Sleep(1000);
125 return i;
126 }
127}