?
Solved

BackgroundWorker w/Mutex - URGENT

Posted on 2006-06-05
5
Medium Priority
?
1,070 Views
Last Modified: 2010-05-18
Currently Im using the BackgroundWorker class in .NET 2.0 to access an FTP class and download a file; however because of the way threading works it all crashes since it isnt waiting for my BackgroundWorker to finish and because there might be more than one BackgroundWorker attempting to use the FTP class which doesnt support that, so the solution was to use Mutex to make each new BackgroundWorker wait until the one before it finishes. That fixes the problem with multiple BackgroundWorkers, however it doesnt fix the problem where the main app isnt waiting for all the BackgroundWorkers to finish working; is it possible to use Mutex to make it wait for the BackgroundWorkers?

This is all in an effort to make the main form stop being unresponsive during FTP uploading/downloading.
0
Comment
Question by:rushtheweb
  • 2
4 Comments
 

Author Comment

by:rushtheweb
ID: 16839284
Here is some code snippets im using to hopefully help paint a better picture.

[The following code is in a for loop which is grabbing each of the selected items from a list box and starting a upload in the background worker thread, while trying to us MuteX to wait for that thread to finish.]

                        storage temp_s = new storage();
                        temp_s.is_directory = false;
                        temp_s.name = lstLocal.Items[index].SubItems[1].Text;
                        temp_s.parent_directory = this.LocalDirectory;

                        Mutex m = new Mutex(false, "FTPLock");
                        uploadworker.RunWorkerAsync(temp_s);
                        m.WaitOne();
                        m.ReleaseMutex();


[The following code is in the DoWork event for the called background worker; the code sets up a MuteX and waits for others to finish if they exist.]

               Mutex m = new Mutex(true, "FTPLock");
              
            m.WaitOne();

            storage temp = (storage)e.Argument;
            upload_file(temp.parent_directory, temp.name);
           
            m.ReleaseMutex();
0
 
LVL 2

Expert Comment

by:HeidarV
ID: 16839545
can't you use IsBusy property of backgroundworker in formclosing?

something like this:

            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                  if (backgroundWorker1.IsBusy)
                        e.Cancel = true;
            }

Heidar
0
 

Author Comment

by:rushtheweb
ID: 16839578
No because the form doesnt close after they finish; the waiting and use of mutex are so the background workers dont try to upload files all at once and crash the app; additionally I need the main GUI to wait for all the background workers to finish before it continues because if it doesnt then it crashes due to it modifying the FTP class the background workers are trying to use to upload files.

Im hoping to somehow use backgroundworkers and mutex to fix my describes problems and to stop the main GUI from freezing during the uploading process.

Thanks :)
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 2000 total points
ID: 16840189
This is simple project I did learning BackgroundWorker class. It shows how to stop BackgroundWorker and wait when it exits. Notice that backWorker_DoWork function periodically tests for CancellationPending and exits when it is true.
Form contains two buttons: btnStart and btnStop, listbox listBox1 and BackgroundWorker backWorker. See Form1_FormClosing and backWorker_DoWork functions.

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

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

            InitializeBackgroundWorker();
        }

        void Application_Idle(object sender, EventArgs e)
        {
            // Start: enabled 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>
        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>
        private void btnStop_Click(object sender, EventArgs e)
        {
            backWorker.CancelAsync();
        }

        /// <summary>
        /// If background work is executed,
        /// stop it synchronously.
        /// </summary>
        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. However, if this line is executed, we have bug in the program
                }
            }
        }

        /// <summary>
        /// Run background process
        /// </summary>
        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>
        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>
        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);
        }

    }
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Hello there! As a developer I have modified and refactored the unit tests which was written by fellow developers in the past. On the course, I have gone through various misconceptions and technical challenges when it comes to implementation. I would…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
With just a little bit of  SQL and VBA, many doors open to cool things like synchronize a list box to display data relevant to other information on a form.  If you have never written code or looked at an SQL statement before, no problem! ...  give i…
Suggested Courses

850 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