maj3091 0 Newbie Poster

Hi,

I'm having a strange issue with a mobile app on WinCE 5 (C# and .NetCF V2), whereby a User Control (custom progressbar), doesn't respond to a request to stop.

The user control was written for us a while back and it's basically a form that fills the screen transparently, then draws the progress bar itself (no controls used). It updates the progress on a timer (very basic, just a cycling bar).

It is created on a thread, so that background comms can continue on the calling form.

The code for creating and controlling the control is as follows:

public class ProgressBarCtrl
 {
     private frmProgress progress = null;
     private string sMsg;
     private int v;
     private int mn;
     private int mx;
     private int MaxWaitTime = 0;

     public ProgressBarCtrl(string sMessage, int value, int min, int max, int maxwait)
     {
         try
         {
             sMsg = sMessage;
             v = value;
             mn = min;
             mx = max;
             MaxWaitTime = maxwait;

             // Create a new thread from which to start the progress bar form
             Thread progressBarThread = new Thread(new ThreadStart(StartProgressBar));
             progressBarThread.Start();
         }
         catch
         {
             //what to do? rethrow a new exception?
         }
     }

     private void StartProgressBar()
     {
         try
         {
             progress = new frmProgress(sMsg, v, mn, mx, MaxWaitTime);
             Application.Run(progress);
         }
         catch
         {
             //what to do? rethrow a new exception?
         }
     }

     public void StopProgressBar()
     {
         try
         {
             if (progress != null)
             {
                 progress.Invoke(new EventHandler(progress.Stop));
                 progress.Dispose();
                 progress = null;
             }
         }
         catch
         {
             //what to do? rethrow a new exception?
         }
     }
 }

The basic outline of the code for the control itself, as as follows:

    class frmProgress : Form
    {

        private System.Windows.Forms.Timer timer;

        int MARGIN = 5;
        int incrementProgress = 1;
        int curProgress = 0;
        long lngTotalProgressTime = 0;
        int minProgress = 0;
        int maxProgress = 1000;
        int maxWait = 2200;
        String txtMessage = "Please Wait...";

        Graphics g = null;
        Rectangle rBox = new Rectangle();
        Rectangle rCaption = new Rectangle();
        Rectangle rCaptionText = new Rectangle();
        Rectangle rProgress = new Rectangle();
        Rectangle rMessage = new Rectangle();
        Font fCaption;
        Font fMessage;

        public frmProgress()
        {
        }

        public frmProgress(string sMessage, int value, int min, int max, int maxW)
        {
            try
            {
                txtMessage = sMessage;
                incrementProgress = value;
                minProgress = min;
                maxProgress = max;
                curProgress = min;
                maxWait = maxW;
                lngTotalProgressTime = 0;

                this.timer = new System.Windows.Forms.Timer();
                this.timer.Interval = 500;  //new 07012008 - was 100
                this.timer.Tick += new System.EventHandler(this.timer_Tick);

                this.MinimizeBox = false;
                this.WindowState = FormWindowState.Maximized;
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                this.Load += new System.EventHandler(this.frmProgress_Load);
            }
            catch
            {
                //what to do? rethrow a new exception?
            }
        }

        void onmousedown(object sender, MouseEventArgs e)
        {
        }

        private void Draw(Boolean bAll)
        {
            try
            {
                if (g == null)
                    return;

                if (bAll)
                {
                    g.FillRectangle(new SolidBrush(SystemColors.Window), rBox);
                    g.FillRectangle(new SolidBrush(SystemColors.ActiveCaption), rCaption);
                    ..... etc, etc. (full Drawing code removed to make it more readable)

                    SolidBrush(SystemColors.ActiveCaptionText), rCaptionText);
                    g.DrawString(txtMessage, fMessage, new SolidBrush(SystemColors.WindowText),    rMessage);
                    g.FillRectangle(new SolidBrush(Color.White), rProgress);
                }
                else
                {
                    Rectangle rCurProgress = new Rectangle();
                    Rectangle rRemainingProgress = new Rectangle();

..... etc, etc. (full Drawing code removed to make it more readable)

                    g.FillRectangle(new SolidBrush(SystemColors.ScrollBar), rCurProgress);
                    g.FillRectangle(new SolidBrush(Color.White), rRemainingProgress);
                }
            }
            catch
            {
                //what to do? rethrow a new exception?
            }
        }

        private void frmProgress_Load(object sender, EventArgs e)
        {
            try
            {
                int screenHeight = Screen.PrimaryScreen.Bounds.Height;
                int screenWidth = Screen.PrimaryScreen.Bounds.Width;

                int pbWidth = screenWidth * 2 / 3;
                int pbHeight = 0;

                g = this.CreateGraphics();

                fCaption = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
                rCaptionText.Size = g.MeasureString("Please wait...", fCaption).ToSize();
                rCaptionText.Size = new Size(pbWidth - 2 * MARGIN, rCaptionText.Size.Height);

                rCaption.Size = new Size(pbWidth, rCaptionText.Size.Height);
                pbHeight += rCaption.Height + MARGIN;

                rProgress.Width = pbWidth - (2 * MARGIN);
                rProgress.Height = 20;
                pbHeight += rProgress.Height + MARGIN;

                fMessage = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular);
                Size messageSize = g.MeasureString(txtMessage, fMessage).ToSize();

                if (messageSize.Width > pbWidth - (2 * MARGIN))
                {
                    int numLines = (messageSize.Width / (pbWidth - (2 * MARGIN))) + 1;

                    messageSize.Width = pbWidth - (2 * MARGIN);
                    messageSize.Height *= numLines;
                }

                rMessage.Size = messageSize;
                pbHeight += rMessage.Height + MARGIN;

                rBox.Size = new System.Drawing.Size(pbWidth, pbHeight < screenHeight ? pbHeight : screenHeight);
                rBox.Location = new Point((screenWidth - rBox.Width) / 2, (screenHeight - rBox.Height) / 2);
                rCaptionText.Location = new Point(rBox.Left + MARGIN, rBox.Top);
                rCaption.Location = new Point(rBox.Left , rBox.Top);
                rProgress.Location = new Point(rBox.Left + MARGIN, rCaption.Bottom + MARGIN);
                rMessage.Location = new Point(rBox.Left + MARGIN, rProgress.Bottom + MARGIN);

                Draw(true);

                this.Show();
                this.TopMost = true;
                timer.Enabled = true;
            }
            catch
            {
                //what to do? rethrow a new exception?
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Draw(true);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }

        public void Stop( object o, EventArgs e)
        {
            this.Close();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            try
            {
                curProgress += incrementProgress;
                lngTotalProgressTime += incrementProgress;

                if (lngTotalProgressTime < maxWait)
                {
                    if (curProgress > maxProgress)
                        curProgress = minProgress;

                    Draw(false);

                }
                else
                {
                    lngTotalProgressTime = 0;
                    this.Close();
                }

            }
            catch
            {
                //what to do? rethrow a new exception?
            }
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
            this.AutoScroll = true;
            this.ClientSize = new System.Drawing.Size(638, 455);
            this.Name = "frmProgress";
            this.Text = "PROGRESS";
            this.ResumeLayout(false);

        }
    }

The code is called from another form using the two methods as follows:

ProgressBarCtrl Progress;
int mintStep = 0;

private void ShowProgressBar(string strText, int intMaxWait)
{
    try
    {
        Progress = new ProgressBarCtrl(strText, 10, 0, 100, intMaxWait);
    }
    catch { }
}

private void HideProgressBar()
{
    try
    {
        Progress.StopProgressBar();
    }
    catch { }
}

So, during normal use, when a long operation is to take place, then we would call ShowProgressBar (which has a timeout) and we would call HideProgressBar when the operation was complete.

In certain circumstances, we may do this a couple of times in a row.

The problem at the customer site, is that he is saying the progressbar stays on screen, for the timeout period, but in debug logs, I can see that HideProgressBar is being called.

So my questions are as follows:

  1. Is there any particular reason that the Stop method would be ignored?

  2. Is the code in the control to Stop the thread adequate enough to ensure that the thread is ended completely?

Just an aside, I'm not expert in mobile development, just trying to pick things up as I go along, so any pointers would be greatly appreciated.

[UPDATE] I've been on the customers site today to see this first hand, but I can't figure out why it's happening. I've tried adding extra code to the progress control, to stop timer and ensure it's disposed off before closing the form, but it's like it isn't seeing the stop command at all sometimes and it just sits there until it times out, then relinquishes control back to the main application.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.