Solved

ListView Control using BackgroundWorker control questions in C#

Posted on 2008-10-22
6
2,913 Views
Last Modified: 2013-12-17
I've run into a bit of a snag and I need some reading resources, help, whatever form I can get it in.
The Form I've created is simple. I dropped a ListView control on to it, a Button and a Label to display the number of files total via my loop routine.

All I'm doing is connected to a remote Server, getting the files from this directory, and then displaying them on the ListView control. However, when I attempt to Call a method routine, I get the following error message:
"Error: Cross-thread operation not valid: Control 'lvwFilesAndFolders' (name of my ListView control)access from a thread other than the thread it was created on". (Line 65 calls PaintListView(string root)).

This happens when the "private void PaintListView(string root)" method is called from the BackgroundWorker.DoWork Event,  and it has references to the ListView Control named "lvwFilesAndFolders". How in the world do I get around this Cross-thread operation?
I have zero experience with Delegates and Multithreading in C#. It appears I'm going to probably need to build the ListView control by code in order to prevent this Cross-thread operation. Anyone have any experience or know of any articles to help me get through this? Not sure where to start.
I can't thank anyone enough,
Wallace
using System;

using System.Collections;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.IO;
 

namespace ParseLogErrors

{

    public partial class Form1 : Form

    {

        private System.Collections.Specialized.StringCollection folderCol;

       

        public Form1()

        {

            InitializeComponent();

            this.labelFileCountDisplay.Text = "";

            CreateHeadersAndFillListView();

            //this.lvwFilesAndFolders.ItemActivate += System.EventHandler(this.lvwFilesAndFolders_ItemActivate);

        }
 

        private void buttonParseLogs_Click(object sender, EventArgs e)

        {

            string dirName = textBoxSearchPath.Text;

                        

            // Set current working directory & verify it exists

            if (Directory.Exists(dirName))

            try

            {

                Directory.SetCurrentDirectory(dirName);

                MessageBox.Show(dirName);

            }

            catch (UnauthorizedAccessException)

            {

                MessageBox.Show("Not authorized to access " + dirName);

                return;

            }

            catch (FileNotFoundException)

            {

                MessageBox.Show("No such directory: " + dirName);

                return;

            }
 

        // Init ListView and folder collection

            //folderCol = new System.Collections.Specialized.StringCollection();

            PaintListView(dirName);

            //folderCol.Add(dirName);

            //PaintListView(@"c:\c# testing");

            //folderCol.Add(@"c:\c# testing");

            //PaintListView(@"\\crprdnsrc03\logs$\sd4\regional");

            //folderCol.Add(@"\\crprdnsrc03\logs$\sd4\regional");
 

            ListView lvi = this.lvwFilesAndFolders;

            bgw.RunWorkerAsync();

        }
 

        private void bw_DoWork(object sender, DoWorkEventArgs e)

        {

            //Lets call the other statements from here

            string dirName = textBoxSearchPath.Text;

            folderCol = new System.Collections.Specialized.StringCollection();

           PaintListView(dirName);

            //folderCol.Add(dirName); 

        }

        

        private void CreateHeadersAndFillListView()

        {

            ColumnHeader colHead;
 

            colHead = new ColumnHeader();

            colHead.Width = 500;

            colHead.Text = "Filename";

            this.lvwFilesAndFolders.GridLines = true;

            this.lvwFilesAndFolders.Columns.Add(colHead);
 

            colHead = new ColumnHeader();

            colHead.Width = 100;

            colHead.Text = "Size";

            this.lvwFilesAndFolders.GridLines = true;

            this.lvwFilesAndFolders.Columns.Add(colHead);
 

            colHead = new ColumnHeader();

            colHead.Width = 200;

            colHead.Text = "Last Accessed";

            this.lvwFilesAndFolders.GridLines = true;

            this.lvwFilesAndFolders.Columns.Add(colHead);

        }
 

        private void PaintListView(string root)

        {

            try

            {

                ListViewItem lvi;

                ListViewItem.ListViewSubItem lvsi;
 

                this.labelDisplayLogInfo.Text = root;

                DirectoryInfo dir = new DirectoryInfo(root);
 

                this.lvwFilesAndFolders.Items.Clear();
 

                DirectoryInfo[] dirs = dir.GetDirectories();

                FileInfo[] files = dir.GetFiles();
 

                this.lvwFilesAndFolders.BeginUpdate();

                

                foreach (System.IO.FileInfo fi in files)

                {

                    lvi = new ListViewItem();

                    lvi.Text = fi.Name;

                    //lvi.ImageIndex = 0;

                    lvi.Tag = fi.FullName;
 

                    lvsi = new ListViewItem.ListViewSubItem();

                    lvsi.Text = formatsizekb(fi.Length);

                    lvi.SubItems.Add(lvsi);
 

                    lvsi = new ListViewItem.ListViewSubItem();

                    lvsi.Text = fi.LastAccessTime.ToString();

                    lvi.SubItems.Add(lvsi);
 

                    this.lvwFilesAndFolders.Items.Add(lvi);
 

                    //Lets count the number of files

                    int file_count = 1;

                    foreach(FileInfo file in files)

                    {

                        this.labelFileCountDisplay.Text = Convert.ToString(file_count++);

                        //progressBar1.Step = 10;

                        //progressBar1.Minimum = 0;

                        //progressBar1.Maximum = 100;

                        //progressBar1 = (file_count * 100) / files.Length;

                    }                                  

                }
 

                this.lvwFilesAndFolders.EndUpdate();

            }

            catch (System.Exception err)

            {

                MessageBox.Show("Error: " + err.Message);

            }
 

            this.lvwFilesAndFolders.View = View.Details;

        }

    

            private void lvwFilesAndFolders_ItemActive(object sender, System.EventArgs e)

        {

            ListView lvw = (ListView)sender;

            string filename = lvw.SelectedItems[0].Tag.ToString();

            Console.WriteLine(filename);

        }
 

        private void buttonExit_Click(object sender, EventArgs e)

        {

            this.Close();

        }

               

        //Formats File size

        private string formatsizekb(long lsize)

        {

            const int iKB = 1024;

            const long lMB = 1048576;
 

            if (lsize < iKB)

                return string.Format("{0:#,#} bytes", lsize);

            else if (lsize >= iKB && lsize < lMB) ;

                return string.Format("{0:#,#} KB", lsize / 1024);

        }

               

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)

        {
 

        }
 

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

        {
 

        }

                

    }

}

Open in new window

0
Comment
Question by:wally_davis
  • 3
  • 3
6 Comments
 
LVL 11

Expert Comment

by:William
ID: 22782233
I have pasted the code below to overcome this for a textbox.
Please review the code and modify for type you need.
If you still need more help please post back and I will gladly help.

BillyDvd
#region Cross Threading Control Delegates for Text Set and Get

        /// <summary>

        /// Call this method to avoid cross threading exceptions when updating a controls text from another thread other than the thread that created it.

        /// </summary>

        /// <param name="Ctrl">Control to update text.</param>

        /// <param name="Text">Text to update as string.</param>

        void SetControlText( Control Ctrl , string Text )

        {

            //ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxmclictl/html/138f38b6-1099-4fd5-910c-390b41cbad35.htm

            if ( Ctrl.InvokeRequired )

            {

                SetControlTextCallBack d = new SetControlTextCallBack( SetControlText );

                this.Invoke( d , new object[ ] { Ctrl , Text } );

            }

            else

                Ctrl.Text = Text;

        }

        delegate void SetControlTextCallBack( Control Ctrl , string Text );
 

        /// <summary>

        /// Call this method to avoid cross threading exceptions when retrieving a controls text from another thread other than the thread that created it.

        /// </summary>

        /// <param name="Ctrl">Control to get text from.</param>

        string GetControlText( Control Ctrl )

        {

            if ( !Ctrl.InvokeRequired )

                return Ctrl.Text;

            else

            {

                //http://www.codeproject.com/csharp/threadsafeforms.asp

                return ( string )Invoke( new GetControlTextCallBack( GetControlText ) , new object[ ] { Ctrl } );

            }

        }

        delegate string GetControlTextCallBack( Control Ctrl );

        #endregion

Open in new window

0
 

Author Comment

by:wally_davis
ID: 22782336
Hi Billy,
Honestly, I've been trying to get this to work with the BackgroundWorker control and I noticed that this may be a bigger challenge for me to overcome. There is nothing in the way of Tutorials out there on C# Winform Controls and threading. I can see where this works for text from a Textbox, but, I'm not sure if it will help me with the ListView Control. I've added the code above and explained as best as I could in detail what I'm attempting to accomplish. It would be nice to have someone go Step by Step to get something like this for me to work. If you want to take a crack please let me know. I would be most thankful.
0
 
LVL 11

Expert Comment

by:William
ID: 22782350
What line does it error on?
Can you post the exception?
Thanks -
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

 

Author Comment

by:wally_davis
ID: 22782728
If you read my first email thread that will cover everything.
However I did leave out which line it was occuring on.
When bw_DoWork Event is processed (on Line 60), it calls the "PaintListView(dirName);" method routine and the  the Error gets thrown at Line # 102 (see my code attachment in first thread).

0
 

Accepted Solution

by:
wally_davis earned 0 total points
ID: 22791294
needed the solution rather quickly and I didn't hear back. However, I've discovered the information I needed anyway.
0
 
LVL 11

Expert Comment

by:William
ID: 22799290
wally_davis,
Can you please post your findings so others can benifit from what you have learned?

BillyDvd
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Summary Displaying images in RichTextBox is a common requirement with limited solutions available. Pasting through clipboard or embedding into RTF content only support static images.  This article describes how to insert Windows control objects int…
In my previous article (http://www.experts-exchange.com/Programming/Languages/.NET/.NET_Framework_3.x/A_4362-Serialization-in-NET-1.html) we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
This video discusses moving either the default database or any database to a new volume.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

760 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

20 Experts available now in Live!

Get 1:1 Help Now