e.Percentage not Accurate

jbsoundjbsound Posts: 35
edited July 24, 2006 11:11AM in SQL Toolkit Previous Versions
I'm noticing that the Status update for the Database Register method does not return the full percentage numbers.

Here is what I am doing:
Private Sub RegisterSource()
        db1.Status = New StatusEventHandler(AddressOf Me.StatusCallbackSourceDB)
        db1.Register(New ConnectionProperties(My.Settings.db1Server, My.Settings.db1Name), Options.Default)
End Sub

Sub StatusCallbackSourceDB(ByVal sender As Object, ByVal e As StatusEventArgs)
        If Not (e.Message Is Nothing) Then
            Me.lstProcess.Items.Add(e.Message.ToString)
            Application.DoEvents()
        End If
        If e.Percentage <> -1 Then
            Me.ultProgressBar.Value = e.Percentage
            Application.DoEvents()
        End If
End Sub

The above code will only report 43% complete when the process finishes.

Am I overlooking something?

Thanks,

JB

Comments

  • Hi there,
    You are not missing anything. Sometimes the % does not get to 100%. It is only a rough % through the task. I am sure that you can understand that some tasks are very difficult to predict, especially as sometimes the sub-elements of the tasks will be run in parallel by using threads.
    Hope this helps
    David
  • Thanks, David.

    Confirmed pretty much what I observed.

    This leaves me with two choices:

    a) Look for another way to determine when the process has finished completely. (Already have another post going on the topic...)

    b) Simply set the progress bar I am using to show the percentage complete manually to 100% when the next statement after calling the SQL process in my code is being handled.

    I may just have to go with option b).

    JB
  • Hi JB,
    If it was me I would use a similar mechanism to the ProgressDialog code in the Packager C# Templates...
    I would have one Progress Dialog box that ran the task(s) in order on 1 other thread. Then "Invoke" the ProgressInformation back onto the main UI thread.
    This would mean that 'Cancel' would work, plus I would not have to have the Do.Events code, which I assume is necessary to get the UI to update?
    Once the method returns I think that task has finished.
    You will also have to be careful of Exceptions being thrown out of the call to Database.Register and the the exception OperationCancelledException, idicating that the task has been user aborted.
    Regards
    David
  • Thanks, David, for your response. It makes sense reading through your reply. Let me muddle through the code template and see how far I get.

    I appreciate your help!

    JB
  • David,

    Quick question:

    Where is the 'ProgressStatusEventHandler' defined?

    I looked through the Packager C# Templates and see the reference to the ProgressStatusEventHandler.

    Working with VB.NET (and the VB.NET samples supplied) I could not locate the above method.

    Thanks,

    JB
  • Well, after a bit more digging I assume that ProgressStatusEventHandler is the same as the StatusEventHandler method. Please correct if wrong.

    Moving on, I implemented the same methodology, I think, from the C# template and am getting only a little bit further.

    Here is what I did:
    Sub UpdateProgress(ByVal sender As Object, ByVal e As StatusEventArgs)
            Debug.Writeline(e.Message + ' ' + e.Percentage)
            Me.Invoke(New StatusEventHandler(AddressOf Me.StatusCallbackDataCompare), New Object() {sender, e})
        End Sub
    
        Sub StatusCallbackDataCompare(ByVal sender As Object, ByVal e As StatusEventArgs)
            Debug.WriteLine(e.Percentage.ToString)
            If Not (e.Message Is Nothing) Then
                Me.lstProcess.Items.Add(e.Message.ToString)
            End If
            Application.DoEvents()
            If e.Percentage <> -1 Then
                Me.ultProgressBar.Value = e.Percentage
            End If
            ' Cancel the operation if the user cancels
            If Me.m_CancelSession Then m_Session.CancelOperation()
        End Sub
    
        Private Sub CompareData()
            Session.Status = New StatusEventHandler(AddressOf Me.UpdateProgress) 
            Session.CompareDatabases(db1, db2, mappings)
            Me.ultProgressBar.Value = 100
        End Sub
    

    Problem is that it still takes an awefull long time for the progress bar to update, meaning that the compare process is well under way before I get any indication of it in my main UI.

    Putting a debug.writeline statement into the UpdateProgress method to see what my percentage and messages look like, I can see that two different threads are working, the one that does the status update reporting and the Invoke thread, which doesn't really start firing until the debug.writeline shows about 35% complete.

    I'm afraid I may need some additional pointers to work through this issue. Ideally, I need to have the visual update happen pretty much at the same time that actual percentage complete is reported.

    With running two different threads it seems to me that one thread is executed way into the process of the first.

    JB
  • Hi JB
    The code is defined in ProgressDialog after the dialog box
    internal interface IProgressExecutor
    {
    		event ProgressStatusEventHandler Status;
    		void CancelExecution();
    		void Execute();
    	}
    
    }
    internal delegate void ProgressStatusEventHandler(object sender, ProgressStatusEventArgs e);
    internal class ProgressStatusEventArgs : EventArgs
    {
    	private string m_Message = null;
    	private int m_Percentage = -1;
    
    	public ProgressStatusEventArgs(string message)
    	{
    		m_Message = message;
    	}
    ....
    }
    
    internal class ProgressCancelException : ApplicationException
    {
    	public ProgressCancelException() {}
    	public ProgressCancelException(string message) : base(message) {}
    	public ProgressCancelException(string message, Exception innerException) : base(message, innerException) {}
    }
    
    So
    ProgressCancelException is roughly equivilant to OperationCancelledException
    ProgressStatusEventArgs is rouglhy equivilant to StatusEventArgs
    IProgressExecutor is roughly equivilant to ICancellable
    Hope that helps.
    David
  • Hi JB,
    I think that you need to run the Session.Compare on another thread, not the UI one....

    To check out some asynch stuff look at: http://www.simple-talk.com/dotnet/windo ... damentals/
    basically I think that your code should be something like....

    Private void MyDialog_Load(object sender, EventArgs e)
    {
        CompareData() //Kick off compare when form is loaded....
    }
    
    Private Sub CompareData() 
         Session.Status = New StatusEventHandler(AddressOf Me.UpdateProgress) 
    
         m_WorkerThread = new Thread(new ThreadStart(CompareDatabases));
         m_WorkerThread.Start();	
         
        End Sub
    
    private void CompareDatabases()
    {
    //Disable OK button now as the task has not started 
    //Enable  Cancel button as task has not started.. 
    
       Session.CompareDatabases(db1, db2, mappings) ;
    Me.Invoke(New StatusEventHandler(AddressOf Me.StatusCallbackDataCompare), New Object() {sender, new StatusEventArgs(100, ""}) 
    //Enable OK button now as the task has completed
    //Disable Cancel button as task has now finished
    }
    
    Please note I have mixed C# with .NET and this will not compile but you get the drift I hope?
    Regards
    David
  • Definitely helps! Thanks for going the extra mile!

    This should do nicely. :)

    JB
Sign In or Register to comment.