原文:
WPF中的多进程(Threading)处理实例(一)
说明:希望通过揣摩这些案例,能进一步了解进程的工作原理。
1.方法一描述的是在同一窗口中,在计算素数的同时而不影响Canvas的工作。
方法1
1 #region Long-Running Calculation in UI Thread 2 3 public delegate void NextPrimeDelegate(); 4 private long num = 3; 5 private bool continueCalculating = false; 6 private bool fNotAPrime = false; 7 8 private void btnPrimeNumber_Click(object sender, RoutedEventArgs e) 9 { 10 if (continueCalculating) 11 { 12 continueCalculating = false; 13 btnPrimeNumber.Content = "Resume"; 14 } 15 else 16 { 17 continueCalculating = true; 18 btnPrimeNumber.Content = "Stop"; 19 20 //获取与此 System.Windows.Threading.DispatcherObject 关联的 System.Windows.Threading.Dispatcher 21 22 //public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method); 23 //按指定的优先级在与 System.Windows.Threading.Dispatcher 关联的线程上异步执行指定的委托。 24 btnPrimeNumber.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new NextPrimeDelegate(CheckNextNumber)); 25 26 } 27 } 28 29 public void CheckNextNumber() 30 { 31 // Reset flag. 32 fNotAPrime = false; 33 34 for (long i = 3; i <= Math.Sqrt(num); i++) 35 { 36 if (num % i == 0) 37 { 38 // Set not-a-prime flag to true. 39 fNotAPrime = true; 40 break; 41 } 42 } 43 44 // If a prime number. 45 if (!fNotAPrime) 46 { 47 tbPrime.Text = num.ToString(); 48 } 49 50 num += 2; 51 52 if (continueCalculating) 53 { 54 //3.In the CheckNextNumber function, because the first parameter 55 //passed into BeginInvoke is DispatcherPriority.SystemIdle(在系统空闲时处理操作。), 56 //all of the CheckNextNumber workitem will not break the UI operation. 57 58 btnPrimeNumber.Dispatcher.BeginInvoke( 59 System.Windows.Threading.DispatcherPriority.SystemIdle, 60 new NextPrimeDelegate(this.CheckNextNumber)); 61 } 62 } 63 64 #endregion
方法2
1 #region Blocking Operation in Worker Thread 2 3 private delegate void NoArgDelegate(); 4 private delegate void OneArgDelegate(Int32[] arg); 5 6 //1.When the Retrieve Data from Server button is clicked, the click handle retrieveData function is called. 7 private void btnRetrieveData_Click(object sender, RoutedEventArgs e) 8 { 9 this.btnRetrieveData.IsEnabled = false; 10 this.btnRetrieveData.Content = "Contacting Server"; 11 12 NoArgDelegate fetcher = new NoArgDelegate(this.RetrieveDataFromServer); 13 14 //2.Then our codes use delegate.BeginInvoke to start a thread from the thread pool. 15 //This thread is used to perform the long operation of retrieving data. 16 fetcher.BeginInvoke(null, null); 17 } 18 19 /// <summary> 20 /// Retrieve data in a worker thread(辅助线程). 21 /// </summary> 22 private void RetrieveDataFromServer() 23 { 24 //3.We use Thread.Sleep(5000) to simulate(模拟) a 5 seconds delay here. 25 // Simulate the delay from network access. 26 Thread.Sleep(5000); 27 28 //4.The codes generate 4 random numbers as data and update them to the UI by calling the Dispatcher.BeginInvoke(). 29 30 // Generate random data to be displayed. 31 Random rand = new Random(); 32 Int32[] data = { 33 rand.Next(1000), rand.Next(1000), 34 rand.Next(1000), rand.Next(1000) 35 }; 36 37 // Schedule the update function in the UI thread. 38 this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, 39 new OneArgDelegate(UpdateUserInterface), data); 40 41 } 42 43 /// <summary> 44 /// Update the UI about the new data. The function runs in the UI thread. 45 /// </summary> 46 /// <param name="data"></param> 47 private void UpdateUserInterface(Int32[] data) 48 { 49 this.btnRetrieveData.IsEnabled = true; 50 this.btnRetrieveData.Content = "Retrieve Data from Server"; 51 this.tbData1.Text = data[0].ToString(); 52 this.tbData2.Text = data[1].ToString(); 53 this.tbData3.Text = data[2].ToString(); 54 this.tbData4.Text = data[3].ToString(); 55 } 56 57 #endregion