Solved

MULTITHREADED WINDOWS APPLICATION IN C#

Posted on 2006-11-05
8
826 Views
Last Modified: 2012-05-05
HAI

IM USING A STATUS BAR WHERE IM DISPLAYING TIME

AND I NEED THE TIME TO GET UPDATED

BUT AT THE SAME TIME THE USER MUST BE ABLE TO DO OTHER INPUTS IN THE SAME FORM

ALSO I NEED TO UPDATE DATABASE IN THE BACKGROUND

I GUESS THIS COULD BE DONE USING MULTITHREADING

WILL SOME ONE HELP ME??????
0
Comment
Question by:VijayDixon
  • 4
  • 3
8 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 17876536
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 125 total points
ID: 17876545
The same using BackgroundWorker class. To make this sample working, create C# Windows Forms application. Paste this code to Form1.Designer.cs replacing existing code:

namespace WorkerThread1
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.listBox1 = new System.Windows.Forms.ListBox();
            this.btnStart = new System.Windows.Forms.Button();
            this.btnStop = new System.Windows.Forms.Button();
            this.backWorker = new System.ComponentModel.BackgroundWorker();
            this.SuspendLayout();
            //
            // listBox1
            //
            this.listBox1.FormattingEnabled = true;
            this.listBox1.Location = new System.Drawing.Point(16, 10);
            this.listBox1.Name = "listBox1";
            this.listBox1.Size = new System.Drawing.Size(323, 173);
            this.listBox1.TabIndex = 0;
            //
            // btnStart
            //
            this.btnStart.Location = new System.Drawing.Point(53, 189);
            this.btnStart.Name = "btnStart";
            this.btnStart.Size = new System.Drawing.Size(99, 28);
            this.btnStart.TabIndex = 1;
            this.btnStart.Text = "Start";
            this.btnStart.UseVisualStyleBackColor = true;
            this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
            //
            // btnStop
            //
            this.btnStop.Location = new System.Drawing.Point(211, 189);
            this.btnStop.Name = "btnStop";
            this.btnStop.Size = new System.Drawing.Size(99, 28);
            this.btnStop.TabIndex = 2;
            this.btnStop.Text = "Stop";
            this.btnStop.UseVisualStyleBackColor = true;
            this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
            //
            // backWorker
            //
            this.backWorker.WorkerReportsProgress = true;
            this.backWorker.WorkerSupportsCancellation = true;
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(353, 229);
            this.Controls.Add(this.btnStop);
            this.Controls.Add(this.btnStart);
            this.Controls.Add(this.listBox1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.ListBox listBox1;
        private System.Windows.Forms.Button btnStart;
        private System.Windows.Forms.Button btnStop;
        private System.ComponentModel.BackgroundWorker backWorker;
    }
}

Paste this code to Form1.cs replacing existing code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WorkerThread1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Application.Idle += new EventHandler(Application_Idle);

            InitializeBackgroundWorker();
        }

        /// <summary>
        /// Set state of controls.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Application_Idle(object sender, EventArgs e)
        {
            // Start: enebled if background worker is not busy (not running)
            btnStart.Enabled = (! backWorker.IsBusy);

            // Stop: enabled if background worker is busy, but not
            // waiting for cancellation.
            btnStop.Enabled = (backWorker.IsBusy  &&
                ! backWorker.CancellationPending );
        }

        /// <summary>
        /// Subscribe to background worker events.
        /// </summary>
        private void InitializeBackgroundWorker()
        {
            backWorker.DoWork += new DoWorkEventHandler(backWorker_DoWork);
            backWorker.ProgressChanged += new ProgressChangedEventHandler(backWorker_ProgressChanged);
            backWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backWorker_RunWorkerCompleted);
        }

        /// <summary>
        /// Start background work.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();

            backWorker.RunWorkerAsync(10);      // 10 is number of steps
        }

        /// <summary>
        /// Stop background work asynchronously
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            backWorker.CancelAsync();
        }

        /// <summary>
        /// If background work is executed,
        /// stop it synchronously.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if ( ! backWorker.IsBusy )
                return;

            // Cancel synchronously (ask and wait)

            this.Enabled = false;       // prevent any user actions

            backWorker.CancelAsync();   // ask to stop

            // Wait when it really stops
            int i = 0;

            while ( backWorker.IsBusy )
            {
                System.Threading.Thread.Sleep(100);
                Application.DoEvents();

                i++;
                if ( i > 20 )
                {
                    break;      // exit anyway, don't way too much
                }
            }
        }

        /// <summary>
        /// Run background process
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void backWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // Get parameters
            BackgroundWorker worker = sender as BackgroundWorker;
            int numberOfSteps = (int)e.Argument;

            for ( int i = 0; i < numberOfSteps; i++ )
            {
                System.Threading.Thread.Sleep(1000);

                if ( worker.CancellationPending )   // test if cancelled
                {
                    e.Cancel = true;
                    break;
                }

                // Report progress and pass user data.
                // This can be used to pass only data, or only progress information,
                // or both.
                worker.ReportProgress(
                    (int)((100.0f * (float)(i+1))/ (float)numberOfSteps),
                    String.Format("Step {0}", i+1));
            }
        }

        /// <summary>
        /// Handle progress notification:
        /// extract and show progress percentage and data.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void backWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            listBox1.Items.Add(String.Format("{0}  {1}%",
                (string)e.UserState,        // user data
                e.ProgressPercentage));     // percentage
        }

        /// <summary>
        /// Background work is completed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void backWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            string s;

            if ( e.Error != null )
            {
                s = e.Error.Message;
            }
            else if ( e.Cancelled )
            {
                s = "Cancelled";
            }
            else
            {
                s = "Finished";
            }

            listBox1.Items.Add(s);
        }

    }
}

Build application and see how it works.
0
 

Expert Comment

by:axsaxs
ID: 17881272
In order to avoid multithreading complexity, consider using

Application.DoEvents()

wisely. For instance, if you have a CPU intensive procedure, consider inserting a DoEvents() into it. Your UI will seem more responsive and ready.

Of course, you will deliver much better results with multithreading. But in my experience, a DoEvents well placed will solve you many problems without the multithreading complexity.

0
 
LVL 1

Author Comment

by:VijayDixon
ID: 17888417
Thank u soo much friend

but i hav a problem

Im using visual studio 2005

if i paste this code and run the program

it says an error in the Dispose function???

wat to do??
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 48

Expert Comment

by:AlexFM
ID: 17888422
This is code from VS 2005. What error exactly?
0
 
LVL 1

Author Comment

by:VijayDixon
ID: 17888585
ok frnd i made that work
but its just filling a list box will i be able to put other controls and will the user be able to interact with those controls when the list box is getting filled

i need to update 1500 records in the background with a thread
and while this is happening
i need to allow the user enter something in the data entry form will that be possible????
0
 
LVL 1

Author Comment

by:VijayDixon
ID: 17888597
what is that backWorker control that i see on the designer window????

is that an user defined control???
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 17888669
You can add other controls to the form and see that it is responsible while thread is running. For example, you can close the program when thread is running. Instead of Listbox you can use any other control, for example, progress bar.
backWorker is instance of BackgroundWorker control. You can see this control in the Toolbox, under Components tag. See also:
http://msdn2.microsoft.com/en-us/system.componentmodel.backgroundworker.aspx
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
A short article about problems I had with the new location API and permissions in Marshmallow
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now