?
Solved

ListView Control using BackgroundWorker control questions in C#

Posted on 2008-10-22
6
Medium Priority
?
2,960 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
Certified OpenStack Administrator Course

We just refreshed our COA course based on the Newton exam.  With 14 labs, this course goes over the different OpenStack services that are part of the certification: Dashboard, Identity Service, Image Service, Networking, Compute, Object Storage, Block Storage, and Orchestration.

 

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

Automating Terraform w Jenkins & AWS CodeCommit

How to configure Jenkins and CodeCommit to allow users to easily create and destroy infrastructure using Terraform code.

Question has a verified solution.

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

Flash (http://en.wikipedia.org/wiki/Adobe_Flash) has evolved over the years to where it has become a masterful tool for displaying content screen.  It has excellent layout placement, UI precision as well as rendering capabilities. This, along with t…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
Suggested Courses

752 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