Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make the progress bar update fast enough?

I'm using a progress bar to show the user how far along the process is. It has 17 steps, and it can take anywhere from ~5 seconds to two or three minutes depending on the weather (well, database)

I had no problem with this in XP, the progress bar went fine, but when testing it in vista I found that it is no longer the case.

For example: if it takes closer to 5 seconds, it might make it a 1/3 of the way through before disappearing because it's completed. Even though it's progress is at 17 of 17, it doesn't show it. I believe this is because of the animation Vista imposes on progress bars and the animation cannot finish fast enough.

Does anyone know how I can correct this?

Here is the code:

This is the part that updates the progress bar, waiting is the form that has the progress bar.

        int progress = 1;
        //1 Cash Receipt Items
        waiting.setProgress(progress, 18, progress, "Cash Receipt Items");
        tblCashReceiptsApplyToTableAdapter1.Fill(rentalEaseDataSet1.tblCashReceiptsApplyTo);
        progress++;
        //2 Cash Receipts
        waiting.setProgress(progress, "Cash Receipts");
        tblCashReceiptsTableAdapter1.Fill(rentalEaseDataSet1.tblCashReceipts);
        progress++;
        //3 Checkbook Codes
        waiting.setProgress(progress, "Checkbook Codes");
        tblCheckbookCodeTableAdapter1.Fill(rentalEaseDataSet1.tblCheckbookCode);
        progress++;
        //4 Checkbook Entries
        waiting.setProgress(progress, "Checkbook Entries");
        tblCheckbookEntryTableAdapter1.Fill(rentalEaseDataSet1.tblCheckbookEntry);
        progress++;
        //5 Checkbooks
        waiting.setProgress(progress, "Checkbooks");
        tblCheckbookTableAdapter1.Fill(rentalEaseDataSet1.tblCheckbook);
        progress++;
        //6 Companies
        waiting.setProgress(progress, "Companies");
        tblCompanyTableAdapter1.Fill(rentalEaseDataSet1.tblCompany);
        progress++;
        //7 Expenses
        waiting.setProgress(progress, "Expenses");
        tblExpenseTableAdapter1.Fill(rentalEaseDataSet1.tblExpense);
        progress++;
        //8 Incomes
        waiting.setProgress(progress, "Incomes");
        tblIncomeTableAdapter1.Fill(rentalEaseDataSet1.tblIncome);
        progress++;
        //9 Properties
        waiting.setProgress(progress, "Properties");
        tblPropertyTableAdapter1.Fill(rentalEaseDataSet1.tblProperty);
        progress++;
        //10 Rental Units
        waiting.setProgress(progress, "Rental Units");
        tblRentalUnitTableAdapter1.Fill(rentalEaseDataSet1.tblRentalUnit);
        progress++;
        //11 Tenant Status Values
        waiting.setProgress(progress, "Tenant Status Values");
        tblTenantStatusTableAdapter1.Fill(rentalEaseDataSet1.tblTenantStatus);
        progress++;
        //12 Tenants
        waiting.setProgress(progress, "Tenants");
        tblTenantTableAdapter1.Fill(rentalEaseDataSet1.tblTenant);
        progress++;
        //13 Tenant Transaction Codes
        waiting.setProgress(progress, "Tenant Transaction Codes");
        tblTenantTransCodeTableAdapter1.Fill(rentalEaseDataSet1.tblTenantTransCode);
        progress++;
        //14 Transactions
        waiting.setProgress(progress, "Transactions");
        tblTransactionTableAdapter1.Fill(rentalEaseDataSet1.tblTransaction);
        progress++;
        //15 Vendors
        waiting.setProgress(progress, "Vendors");
        tblVendorTableAdapter1.Fill(rentalEaseDataSet1.tblVendor);
        progress++;
        //16 Work Order Categories
        waiting.setProgress(progress, "Work Order Categories");
        tblWorkOrderCategoryTableAdapter1.Fill(rentalEaseDataSet1.tblWorkOrderCategory);
        progress++;
        //17 Work Orders
        waiting.setProgress(progress, "Work Orders");
        tblWorkOrderTableAdapter1.Fill(rentalEaseDataSet1.tblWorkOrder);
        progress++;
        //18 Stored procs
        waiting.setProgress(progress, "Stored Procedures");
        getAllCheckbookBalancesTableAdapter1.Fill(rentalEaseDataSet1.GetAllCheckbookBalances);
        getAllTenantBalancesTableAdapter1.Fill(rentalEaseDataSet1.GetAllTenantBalances);
        //getCheckbookBalanceTableAdapter1;
        //getTenantBalanceTableAdapter1;
        getTenantStatusID_CurrentTableAdapter1.Fill(rentalEaseDataSet1.GetTenantStatusID_Current);
        getTenantStatusID_FutureTableAdapter1.Fill(rentalEaseDataSet1.GetTenantStatusID_Future);
        getTenantStatusID_PastTableAdapter1.Fill(rentalEaseDataSet1.GetTenantStatusID_Past);
        selectVacantRentalUnitsByIDTableAdapter1.Fill(rentalEaseDataSet1.SelectVacantRentalUnitsByID);
        getRentBasedBalancesTableAdapter1.Fill(rentalEaseDataSet1.GetRentBasedBalances);
        getAgingBalanceTableAdapter2.Fill(rentalEaseDataSet1.GetAgingBalance);


        waiting.Close();

Here is the waiting form:

public partial class PleaseWaitDialog : Form {
    public PleaseWaitDialog() {
        CheckForIllegalCrossThreadCalls = false;
        InitializeComponent();
    }

    public void setProgress(int current, int max, int min, string loadItem) {
        Debug.Assert(min <= max, "Minimum is bigger than the maximum!");
        Debug.Assert(current >= min, "The current progress is less than the minimum progress!");
        Debug.Assert(current <= max, "The progress is greater than the maximum progress!");

        prgLoad.Minimum = min;
        prgLoad.Maximum = max;
        prgLoad.Value = current;
        lblLoadItem.Text = loadItem;
    }

    public void setProgress(int current, string loadItem) {
        this.setProgress(current, prgLoad.Maximum, prgLoad.Minimum, loadItem);
    }
}
like image 777
Malfist Avatar asked Jun 10 '09 18:06

Malfist


2 Answers

The reason for this whole mess is the interpolating animation effect introduced by Vista and W7. It has aboslutely nothing to do with thread blocking issues. Calling setProgress() or setting the Value property driectly, triggers an animation effect to occur, which I will explain how to cheat:

I came up with a hack of setting the maximum according to a fixed value. The maximum property does not trigger the effect, thus you get to freely move the progress around with instant response.

Remember that the actual shown progress is given by: ProgressBar.Value / ProgressBar.Maximum. With this in mind, the example below will move the progress from 0 to 100, repensented by i:

ProgressBar works like this:  
progress = value / maximum

therefore:
maximum = value / progress

I added some scaling factors needed, should be self explanatory:

progressBar1.Maximum *= 100;
progressBar1.Value = progressBar1.Maximum / 100;
for (int i = 1; i < 100; i++)
{
    progressBar1.Maximum = (int)((double)progressBar1.Value / (double)(i + 1) * 100);
    Thread.Sleep(20);
}
like image 74
Silas Hansen Avatar answered Oct 20 '22 12:10

Silas Hansen


Vista introduced an animation effect when updating the progress bar - it tries to smoothly scroll from the previous position to the newly-set position, which creates a nasty time lag in the update of the control. The lag is most noticeable when you jump a progress bar in large increments, say from 25% to 50% in one jump.

As another poster pointed out, you can disable the Vista theme for the progress bar and it will then mimic the behavior of XP progress bars.

I have found another workaround: if you set the progress bar backwards, it will immediately paint to this location. So, if you want to jump from 25% to 50%, you would use the (admittedly hackish) logic:

progressbar.Value = 50;
progressbar.Value = 49;
progressbar.Value = 50;

I know, I know - it's a silly hack - but it does work!

like image 24
Mark Lansdown Avatar answered Oct 20 '22 13:10

Mark Lansdown