WorkerEventHandler.BeginInvoke() questions.
-
I have an application that is reading thousands of rows form an access database running calculations then updating the data. I'm using an Async. Design pattern that I'd found on MSDN and am getting my butt handed to me.
public void StartRecalculation() { try { FillArrayList(); for ( int num = 0; num < m_Manifest.Count; num++ ) { // Task IDs are Guids. Guid taskId = Guid.NewGuid(); // Start the asynchronous task. this.CalculateStartAsync( Int32.Parse( m_Manifest[ num ].ToString() ), taskId ); } // end of for loop. } // end of try catch ( Exception ex ) { AddToErrorReport( ex.ToString() ); }// end of catch } // end of StartRecalculation public void CalculateStartAsync( int _ticket, object taskId ) { // Create an AsyncOperation for taskId. AsyncOperation asyncOp = AsyncOperationManager.CreateOperation( taskId ); // Multiple threads will access the task dictionary, // so it must be locked to serialize access. lock ( userStateToLifetime.SyncRoot ) { if ( userStateToLifetime.Contains( taskId ) ) { throw new ArgumentException( "Task ID parameter must be unique", "taskId" ); } // end of userStateToLifetime.Contains( taskId ) userStateToLifetime[ taskId ] = asyncOp; } // end of lock this // Start the asynchronous operation. WorkerEventHandler workerDelegate = new WorkerEventHandler( CalculateWorker ); workerDelegate.BeginInvoke( _ticket, asyncOp, null, null ); } //end of CalculateStartAsync
My question is when creating the WorkerEventHandler ie..WorkerEventHandler workerDelegate = new WorkerEventHandler( CalculateWorker );
And then calling the BeginInvokeworkerDelegate.BeginInvoke( _ticket, asyncOp, null, null );
Is this creating a new instance of the CalculateWorker Method and other referenced methods? Will I need to isolate my tableAdapters to each method and create new each time or will I be able to us a global Dataset to store and manipulate the inforamtion. I'm having trouble completing anything within my database. I'm getting random rows not found and outOfIndex exceptions. If anyone has any advice on the topic, please help. thanks.I'm listening but I only speak GEEK.
-
I have an application that is reading thousands of rows form an access database running calculations then updating the data. I'm using an Async. Design pattern that I'd found on MSDN and am getting my butt handed to me.
public void StartRecalculation() { try { FillArrayList(); for ( int num = 0; num < m_Manifest.Count; num++ ) { // Task IDs are Guids. Guid taskId = Guid.NewGuid(); // Start the asynchronous task. this.CalculateStartAsync( Int32.Parse( m_Manifest[ num ].ToString() ), taskId ); } // end of for loop. } // end of try catch ( Exception ex ) { AddToErrorReport( ex.ToString() ); }// end of catch } // end of StartRecalculation public void CalculateStartAsync( int _ticket, object taskId ) { // Create an AsyncOperation for taskId. AsyncOperation asyncOp = AsyncOperationManager.CreateOperation( taskId ); // Multiple threads will access the task dictionary, // so it must be locked to serialize access. lock ( userStateToLifetime.SyncRoot ) { if ( userStateToLifetime.Contains( taskId ) ) { throw new ArgumentException( "Task ID parameter must be unique", "taskId" ); } // end of userStateToLifetime.Contains( taskId ) userStateToLifetime[ taskId ] = asyncOp; } // end of lock this // Start the asynchronous operation. WorkerEventHandler workerDelegate = new WorkerEventHandler( CalculateWorker ); workerDelegate.BeginInvoke( _ticket, asyncOp, null, null ); } //end of CalculateStartAsync
My question is when creating the WorkerEventHandler ie..WorkerEventHandler workerDelegate = new WorkerEventHandler( CalculateWorker );
And then calling the BeginInvokeworkerDelegate.BeginInvoke( _ticket, asyncOp, null, null );
Is this creating a new instance of the CalculateWorker Method and other referenced methods? Will I need to isolate my tableAdapters to each method and create new each time or will I be able to us a global Dataset to store and manipulate the inforamtion. I'm having trouble completing anything within my database. I'm getting random rows not found and outOfIndex exceptions. If anyone has any advice on the topic, please help. thanks.I'm listening but I only speak GEEK.
Hi Arejay, I am not a db specialist at all, but this may help: your code starts a number of threads each executing the "CalculateWorker" method. BTW: methods dont get instantiated, they just get executed, using the local context (e.g. the stack belonging to the executing thread). So the app has several threads executing the same code, if that code refers to global data (all your class members) you may get concurrency problems. If for instance you create and use some object (maybe a table adapter) and suddenly that object gets manipulated by multiple threads, anything can happen. Rather than using such shared data (and trying to add all necessary locks), I would advise to give each thread its own data, i.e. instantiate a "job" object for each thread you create (better yet, create the thread inside the job object). Hope this helps. :)
Luc Pattyn [My Articles]
-
Hi Arejay, I am not a db specialist at all, but this may help: your code starts a number of threads each executing the "CalculateWorker" method. BTW: methods dont get instantiated, they just get executed, using the local context (e.g. the stack belonging to the executing thread). So the app has several threads executing the same code, if that code refers to global data (all your class members) you may get concurrency problems. If for instance you create and use some object (maybe a table adapter) and suddenly that object gets manipulated by multiple threads, anything can happen. Rather than using such shared data (and trying to add all necessary locks), I would advise to give each thread its own data, i.e. instantiate a "job" object for each thread you create (better yet, create the thread inside the job object). Hope this helps. :)
Luc Pattyn [My Articles]
Thank you! So... I've created a worker class and I'm creating multiple instances of the worker. Within the worker class I create an asyn thread using the BeginInvoke. Now I need update the calling form.
public delegate void CalculationCompletedEventHandler( object sender, CalculationCompletedEventArgs e );
In the Worker class:public class Worker : Component { //... public event CalculationCompletedEventHandler CalculationCompleted; //.. private void doCalculationCompleted( object operationState ){ CalculationCompletedEventArgs e = operationState as CalculationCompletedEventArgs; OnCalculationCompleted( e ); } protected void OnCalculationCompleted( CalculationCompletedEventArgs e ){ if ( CalculationCompleted != null ) { CalculationCompleted( this, e ); } }
On the form:internal void OnUpdateProgress( object sender, CalculationCompletedEventArgs e ){ if ( this.InvokeRequired ){ this.Invoke( doProgressUpdate, new object[] { sender, e } ); }else{ lock ( this ){ //....Do Stuff } } } Worker w = new Worker(id); w.CalculationCompleted += OnUpdateProgress;
In the above is the doCalculationCompleted method needed in the Worker Class? I'll update my code and let you know how it went. Thanks again.I'm listening but I only speak GEEK.
-
Thank you! So... I've created a worker class and I'm creating multiple instances of the worker. Within the worker class I create an asyn thread using the BeginInvoke. Now I need update the calling form.
public delegate void CalculationCompletedEventHandler( object sender, CalculationCompletedEventArgs e );
In the Worker class:public class Worker : Component { //... public event CalculationCompletedEventHandler CalculationCompleted; //.. private void doCalculationCompleted( object operationState ){ CalculationCompletedEventArgs e = operationState as CalculationCompletedEventArgs; OnCalculationCompleted( e ); } protected void OnCalculationCompleted( CalculationCompletedEventArgs e ){ if ( CalculationCompleted != null ) { CalculationCompleted( this, e ); } }
On the form:internal void OnUpdateProgress( object sender, CalculationCompletedEventArgs e ){ if ( this.InvokeRequired ){ this.Invoke( doProgressUpdate, new object[] { sender, e } ); }else{ lock ( this ){ //....Do Stuff } } } Worker w = new Worker(id); w.CalculationCompleted += OnUpdateProgress;
In the above is the doCalculationCompleted method needed in the Worker Class? I'll update my code and let you know how it went. Thanks again.I'm listening but I only speak GEEK.
Hi Arejay, you can do with and without a completion event. WITH: the callee provides such an event, caller attaches something to it. WITHOUT: the caller implements some interface (say IDone, with a Done() method), and the callee's constructor accepts an object argument that implements that interface; when done the callee just executes the IDone, hence executing the caller's Done() code. The advantage of events (being able to attach multiple delegates) typically is of no value in the given situation... PS: two remarks about your OnUpdateProgress method: - it invokes doProgressUpdate, the normal pattern is to invoke itself - the lock may not be needed, since the else part executes on the UI thread, hence needs not to be re-entrant. (If other pieces of code contain the same lock and execute on another thread, net result is such thread may keep the UI thread from running, which may harm the responsiveness) Regards. :)
Luc Pattyn [My Articles]
-
Hi Arejay, you can do with and without a completion event. WITH: the callee provides such an event, caller attaches something to it. WITHOUT: the caller implements some interface (say IDone, with a Done() method), and the callee's constructor accepts an object argument that implements that interface; when done the callee just executes the IDone, hence executing the caller's Done() code. The advantage of events (being able to attach multiple delegates) typically is of no value in the given situation... PS: two remarks about your OnUpdateProgress method: - it invokes doProgressUpdate, the normal pattern is to invoke itself - the lock may not be needed, since the else part executes on the UI thread, hence needs not to be re-entrant. (If other pieces of code contain the same lock and execute on another thread, net result is such thread may keep the UI thread from running, which may harm the responsiveness) Regards. :)
Luc Pattyn [My Articles]