locked
GUI update problem RRS feed

  • Question

  • Hi,
    I'm new to C# and I need some help on how to update the GUI in my application.
    I have a list of files that I process and then delete. I want the file list (in the GUI) to be updated as the files are processed, but the GUI is not updated until all the files are processed (when the function doing the file processing has finished)
    How do I update the GUI while the file processing function is running?
    Any suggestions are appreciated.

    Monday, June 16, 2008 12:57 PM

Answers

  • Hello,

    If you are using "BackgroundWorker" class, move the code which is in "start_click" to "Backgroundworkers" "DoWork" event handler. Inside "ProgressChanged" event handler, update the progress bar. Say you have a "BackgroundWorker" instance named "worker".

    worker = new BackgroundWorker(); 
           
    // Hooking events 
    worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); //Fired when progress changes 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); // Fired when worker completes or cancels 
             
    // Setting worker bahaviour 
    worker.WorkerReportsProgress = true
    worker.WorkerSupportsCancellation = true
     
    // Doing the work 
    worker.RunWorkerAsync();    // Start the work on DoWork event handler 
     

    Write the above code inside start_click. Inside "worker_DoWork" method, write your code for processing. To update progress, call "worker.ReportProgress()". Inside "worker_progresschanged" event handler, write code to update the progress bar.

    Hope this will help




    Sincerly, Navaneeth.K.N
    • Marked as answer by jack 321 Friday, June 20, 2008 10:31 AM
    Thursday, June 19, 2008 12:32 PM

All replies

  • You might want to study how threading works is C#. You will have to create a separate thread for your application that will process the files and update the GUI. As Microsoft states on their documentation,

    The advantage of threading is the ability to create applications that use more than one thread of execution. For example, a process can have a user interface thread that manages interactions with the user and worker threads that perform other tasks while the user interface thread waits for user input.

    Click here for full
    Microsoft Documentation

    Hope this helps,
    -Tudor



    19 years old student http://www.tudoralex.com
    Monday, June 16, 2008 1:01 PM
  • This is happening because you are running everything in the main thread. You need to run the deletion process in a separate thread to keep your GUI active. Use "BackgroundWorker" class to do this easily. It provides internal mechanism to handle GUI updates and progress reporting. I have an article on this. Please read Threading with BackgroundWorker

    Hope this helps



    Sincerly, Navaneeth.K.N
    • Proposed as answer by Navaneeth Thursday, June 19, 2008 8:35 AM
    Monday, June 16, 2008 1:24 PM
  •   Hi,
    thanks for the help.
    I've tried both the background worker and delegate that i found in the documentation, but the gui is not updated until the loop doing the file processing has finished, so I still have the same problem :(
    I found a producer consumer threading example that I tried, but when I try do update the gui delegate does not work.
    Maybe I'm doing this the wrong way, please help.
    Thursday, June 19, 2008 5:24 AM
  • Please post the code you used. 
    Sincerly, Navaneeth.K.N
    Thursday, June 19, 2008 7:20 AM
  • Hi KingVoodoo,

    Maybe you can try to take a look at how to update a Windows Form control in a separate Worker thread, The LINK below.

    How to: Make Thread-Safe Calls to Windows Forms Controls 

    Based on my experience, the BackgroundWorker class is a nice choice for this situation, if you still cannot figure the issue out, please post the detailed code here and let us know what the problem is.

    Regards,

    Xun


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Edited by jack 321 Thursday, June 19, 2008 7:35 AM add a word
    Thursday, June 19, 2008 7:33 AM
  • Hi,
    thanks again.
    Here is the code i'm using (I hope that's all you need)

     

    private void UpdateGUI()  
            {  
                while (true)  
                {  
                    if (bInTransfer && !bComplete)  
                    {  
                        // Update status  
                        SetStatus("In Transfer");  
                        bInTransfer = false;  
                    }  
                    if (bComplete && !bInTransfer)  
                    {  
                        // Update status  
                        SetStatus("Transfer Complete");  
                        bComplete = false;  
                    }  
                }  
            } 
    public Form1()  
            {  
                ...  
                // start gui update thread  
                try 
                {  
                    guiUpdateThread = new Thread(new ThreadStart(UpdateGUI));  
                    guiUpdateThread.Start();  
     
                }  
                catch (Exception e)  
                {  
                    guiUpdateThread.Abort();  
                }  
            } 
    private void Start_Click(object sender, EventArgs e)  
            {  
                //Check input fields  
                if ((tbDir.Text != "") && (tbIP.Text != "") && (tbDelay.Text != "") && (tbPort.Text != ""))  
                {  
                    // Start Working  
                    if (IsDataValid())  
                    {  
     
                        //---------------------------------------------------------------------  
                        if (intNrOfFiles == 0)  
                        {  
                            //Initialize  
                            intMtu = Convert.ToInt32(tbMtu.Text);  
                            aData = new byte[intMtu];  
     
                            //Search dir for files  
                            aFiles = Directory.GetFiles(tbDir.Text, "*.*");  
                            // Get number of files in dir.  
                            intNrOfFiles = aFiles.Length;  
                            //Add files to list view  
                            foreach (String strFile in aFiles)  
                            {  
                                ListViewItem lviEntry = new ListViewItem(strFile);  
                                lviEntry.SubItems.Add("Pending");  
                                listFile.Items.Add(lviEntry);  
                            }  
     
                            //Process files in list  
                            for (int i = 0; i < intNrOfFiles; i++)  
                            {  
                                intFileIndex = i;  
                                bInTransfer = true;  
                                strFileToSend = listFile.Items[intFileIndex].Text;  
                                  
                                try 
                                {  
                                    fi = new FileInfo(strFileToSend);  
                                }  
                                catch (System.IO.FileNotFoundException ex)  
                                {  
                                    MessageBox.Show(ex.Message);  
                                }  
     
                                //Get file size  
                                lFileSize = fi.Length;  
                                //Get file name  
                                strFileName = fi.Name;  
                                //Get nr of packets to send  
                                intNrOfPackets = (int)lFileSize / intMtu;  
                                //Set progressbar values  
                                int intSteps = intNrOfPackets + 1;  
                                if (intSteps >= 100)  
                                {  
                                    progressBar1.Step = 1;  
                                    progressBar1.Maximum = intSteps;  
                                }  
                                else 
                                {  
                                    progressBar1.Step = 100 / intSteps;  
                                    progressBar1.Maximum = progressBar1.Step * intSteps;  
                                }  
                                  
                                //Create stream reader to read file  
                                fs = new FileStream(strFileToSend, FileMode.Open, FileAccess.Read, FileShare.Read);  
                                fsTarget = new FileStream("C:\\Temp\\Target\\" + strFileName, FileMode.CreateNew);  
     
                                //Read file  
                                for (int j = 0; j < intNrOfPackets; j++)  
                                {  
                                    //  
                                    fs.Read(aData, 0, intMtu);  
     
                                    //Write to new file  
                                    fsTarget.Write(aData, 0, intMtu);  
     
                                    //increase progressbar  
                                    progressBar1.PerformStep();  
                                }  
                                // Read the last bit of the file.  
                                aFinalData = new byte[(int)lFileSize % intMtu];  
                                fs.Read(aFinalData, 0, (int)lFileSize % intMtu);  
                                fs.Close();  
     
                                fsTarget.Write(aFinalData, 0, (int)lFileSize % intMtu);  
                                fsTarget.Flush();  
                                fsTarget.Close();  
     
                                //Increment progressbar  
                                progressBar1.PerformStep();  
                      
                                //Update Status  
                                bInTransfer = false;  
                                bComplete = true;  
     
                                //Reset progress bar  
                                progressBar1.Value = 0;  
                            }  
                            ...  
                        }  
                        //--------------------------------------------------------------------*/  
                    }// End IsDataValid()  
                }  
                else 
                {  
                    ...  
                } 
     
    private void SetStatus(String _text)  
            {  
                if (listFile.InvokeRequired)  
                {  
                    SetTextCallback d = new SetTextCallback(SetStatus);  
                    this.Invoke(d, new object[] { _text});  
                }  
                else 
                {  
                    this.listFile.Items[intFileIndex].SubItems[intFileIndex].Text = _text;  
                }  
            } 

    I want the gui to be updated while Start_Click is running.
    Right now the list of files is not displayed until Start_Click has ended.
    I know there are some synchronization issues, but if I can't see the list thats not a problem.

    Thanks in advance.
    Thursday, June 19, 2008 11:51 AM
  • Hello,

    If you are using "BackgroundWorker" class, move the code which is in "start_click" to "Backgroundworkers" "DoWork" event handler. Inside "ProgressChanged" event handler, update the progress bar. Say you have a "BackgroundWorker" instance named "worker".

    worker = new BackgroundWorker(); 
           
    // Hooking events 
    worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); //Fired when progress changes 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); // Fired when worker completes or cancels 
             
    // Setting worker bahaviour 
    worker.WorkerReportsProgress = true
    worker.WorkerSupportsCancellation = true
     
    // Doing the work 
    worker.RunWorkerAsync();    // Start the work on DoWork event handler 
     

    Write the above code inside start_click. Inside "worker_DoWork" method, write your code for processing. To update progress, call "worker.ReportProgress()". Inside "worker_progresschanged" event handler, write code to update the progress bar.

    Hope this will help




    Sincerly, Navaneeth.K.N
    • Marked as answer by jack 321 Friday, June 20, 2008 10:31 AM
    Thursday, June 19, 2008 12:32 PM
  • For questions and discussions regarding client application development using Windows Forms controls and features, please see http://forums.microsoft.com/msdn/ShowForum.aspx?ForumID=8&SiteID=1

    http://www.peterRitchie.com/blog
    • Marked as answer by Peter Ritchie Friday, June 20, 2008 4:49 PM
    • Unmarked as answer by KingVoodoo Thursday, October 16, 2008 8:01 AM
    Friday, June 20, 2008 4:48 PM