Using system;using system.collections;using system.collections.specialized;using system.componentmodel;using System.data;using system.drawing;using system.globalization;using system.threading;using System.Windows.Forms; namespace asyncprogramdemo{public delegate void Progresschangedeventhandler (ProgressChangedEventArgs e); public delegate void Calculateprimecompletedeventhandler (object sender, CalculatePrimeCompletedEventArgs e) ; public class Primenumbercalculator:component {public event Progresschangedeventhandler progresschanged; public event Calculateprimecompletedeventhandler calculateprimecompleted; Private SendOrPostCallback onprogressreportdelegate; Private SendOrPostCallback oncompleteddelegate; protected virtual void Initializedelegates () {onprogressreportdelegate = new SENDORPOSTC Allback (reportprogress); Oncompleteddelegate = new SendOrPostCallback (Calculatecompleted); } Private delegate void Workereventhandler (int numbertocheck, asyncoperation asyncop); Private HybridDictionary userstatetolifetime = new HybridDictionary (); Public PrimeNumberCalculator () {//initializecomponent (); Initializedelegates (); }//This method was invoked via the AsyncOperation object,//So it was guaranteed to being executed on the Corr ECT thread. private void Calculatecompleted (object operationstate) {CalculatePrimeCompletedEventArgs E = Operationstate as CalculatePrimeCompletedEventArgs; Oncalculateprimecompleted (e); }//This method was invoked via the AsyncOperation object,//So it was guaranteed to being executed on the Corr ECT thread. private void ReportProgress (object state) {ProgressChangedEventArgs E = state as Progres SchangedeventarGs Onprogresschanged (e); } protected void oncalculateprimecompleted (CalculatePrimeCompletedEventArgs e) {if ( calculateprimecompleted = null) {calculateprimecompleted (this, e); }} protected void Onprogresschanged (ProgressChangedEventArgs e) {if (progresschanged! = NULL) {progresschanged (e); }}//This is the method of the underlying, free-threaded//asynchronous behavior would invoke. This would happen on//an arbitrary thread. private void Completionmethod (int numbertotest, int firstdivisor, BOOL IsPrime, Exception Exception, BOOL canceled, AsyncOperation Asyncop) {//If the task WA s not previously canceled,//Remove the task from the Lifetime collection. if (!canceled) {Lock (userstatetolifetime.syncroot) {Userstatetolifetime.remove (asyncop.usersuppliedstate); }}//Package The results of the operation in A///CalculatePrimeCompletedEventArgs. CalculatePrimeCompletedEventArgs e = new CalculatePrimeCompletedEventArgs (numbert Otest, Firstdivisor, IsPrime, exception, canceled, Asyncop.usersuppliedstate); End the task. The Asyncop object is responsible//for marshaling. Asyncop.postoperationcompleted (Oncompleteddelegate, E); Note that after the call to operationcompleted,//ASYNCOP are no longer usable, and any attempt to use it Would cause an exception to be thrown. }//Utility method for determining if a//task have been CancEled. private bool Taskcanceled (object taskId) {return (userstatetolifetime[taskid] = = null); }//This method performs the actual prime number computation. It is executed on the worker thread. private void CalculateWorker (int numbertotest, asyncoperation asyncop) {bool IsP Rime = false; int firstdivisor = 1; Exception e = null; Check the task is still active. The operation May has been canceled before//The thread was scheduled. if (! Taskcanceled (asyncop.usersuppliedstate)) {try {//Find all T He prime numbers up to//the square root of numbertotest. ArrayList primes = buildprimenumberlist (numbertotest, ASYNCOP); Now we have a list of primes leSS than//Numbertotest. IsPrime = IsPrime (primes, numbertotest, out Firstdiv Isor); } catch (Exception ex) {e = ex; }}//calculateprimestate CalcState = new CalculatePrimeState (//Numbertotest, Firstdivisor,//IsPrime,//E,//taskcanceled (a syncop.usersuppliedstate),//ASYNCOP); This. Completionmethod (CalcState); This. Completionmethod (Numbertotest, Firstdivisor, IsPrime, E, Taskcanceled (asyncop.usersuppliedstate), ASYNCOP); Completionmethoddelegate (CalcState); }//This method computes the list of primes numbers used by the IsPrime method. Private ArrayList buildprimenumberlist (int numbertotest, asyncoperation asyncop) { ProgressChangedEventArgs e = null; ArrayList primes = new ArrayList (); int firstdivisor; int n = 5; Add the first prime numbers. Primes. ADD (2); Primes. ADD (3); Do the work. while (n < numbertotest &&!) Taskcanceled (asyncop.usersuppliedstate)) {if (IsPrime (primes, N, out Firstdivisor)) {//Report to the client, a prime was found. E = new CalculatePrimeProgressChangedEventArgs (n, (int) ((float) n/(float) n Umbertotest *), asyncop.usersuppliedstate); Asyncop.post (This.onprogressreportdelegate, E); Thread.Sleep (1); Primes. ADD (n); Yield the rest of this time slice. Thread.Sleep (0); }//Skip even numbers. n + = 2; } return primes; }//This method tests N for primality against the list of//prime numbers contained in the primes Paramet Er. private bool IsPrime (ArrayList primes, int n, out int firstdivisor) { BOOL Founddivisor = false; BOOL Exceedssquareroot = false; int i = 0; int divisor = 0; Firstdivisor = 1; Stop the Search if:///There is no more primes in the list,//There is a divisor of n in the Li St, or//There is a prime this is larger than//the square root of N. while ((I < primes. Count) &&!founddivisor &&!exceedssqUareroot) {//The divisor variable would be is the smallest//prime number not yet Tried. divisor = (int) primes[i++]; Determine whether the divisor is greater//than the square root of N. if (divisor * divisor > N) {exceedssquareroot = true; }//Determine whether the divisor is a factor of N. else if (n% divisor = = 0) {firstdivisor = divisor; Founddivisor = true; }} return!founddivisor; }//This method starts an asynchronous calculation. First, it checks the supplied task ID for uniqueness. If TaskId is unique, it creates a new Workereventhandler//and calls their BeginInvoke method to start the CALCU Lation. public virtual void CalculatePrimeAsync (int Numbertotest, Object taskId) {//Create an asyncoperation for taskId. AsyncOperation Asyncop = asyncoperationmanager.createoperation (taskId); Multiple threads would access the task dictionary,//So it must is locked to serialize access. Lock (Userstatetolifetime.syncroot) {if (Userstatetolifetime.contains (taskId)) { throw new ArgumentException ("Task ID parameter must be unique", "TaskId"); } Userstatetolifetime[taskid] = Asyncop; }//Start the asynchronous operation. Workereventhandler workerdelegate = new Workereventhandler (calculateworker); Workerdelegate.begininvoke (numbertotest, ASYNCOP, NULL, NULL) ; }//This method cancels a pending Asynchronous operation. public void CancelAsync (object taskId) {asyncoperation Asyncop = Userstatetolifetime[taskid] as Asyncop eration; if (ASYNCOP! = null) {lock (userstatetolifetime.syncroot) {u Serstatetolifetime.remove (TASKID); }}}} public class Calculateprimecompletedeventargs:asynccompletedeventargs { private int numbertotestvalue = 0; private int firstdivisorvalue = 1; private bool Isprimevalue; Public CalculatePrimeCompletedEventArgs (int numbertotest, int firstdivisor, BOOL IsPrime , Exception E, BOOL canceled, object state): Base (E, Canceled, state) {this.numbertotestvalue = numbertotest; This.firstdivisorvalue = Firstdivisor; This.isprimevalue = IsPrime; } public intNumbertotest {get {//Raise an exception if the operation failed or Was canceled. Raiseexceptionifnecessary (); If The operation is successful, return the/property value. return numbertotestvalue; }} public int Firstdivisor {get {//Raise an exception if the Operation failed or//was canceled. Raiseexceptionifnecessary (); If The operation is successful, return the/property value. return firstdivisorvalue; }} public bool IsPrime {get {//Raise an exception if the Ope Ration failed or//was canceled. Raiseexceptionifnecessary (); If The operation was successful, return the Property value. return isprimevalue; }}} public class Calculateprimeprogresschangedeventargs:progresschangedeventargs {Priva te int latestprimenumbervalue = 1; Public CalculatePrimeProgressChangedEventArgs (int latestprime, int progresspercentage, O Bject usertoken): Base (Progresspercentage, usertoken) {this.latestprimenumbervalue = latest Prime; } public int LatestPrimeNumber {get {return latestprimenumbervalue; } } }}
Asynchronous Programming Design Pattern Demo-primenumbercalculator