Solved

ListView Control using BackgroundWorker control questions in C#

Posted on 2008-10-22
6
2,946 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

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

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

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

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

734 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