简体   繁体   中英

Cross-Threading issue with listView

OK before everyone post duplicate let me inform you I have looked at all those other post and im still lost some say use delegates or background worker etc... but how would I make this thread safe i want to delete the files on its own thread.

here is the code that i am working with.

private void button1_Click(object sender, EventArgs e)
{
    cleanFiles.RunWorkerAsync();
}

private void cleanFiles_DoWork(object sender, DoWorkEventArgs e)
{
    if (listView1.CheckedItems.Count != 0)
    {
        // If so, loop through all checked files and delete.
        for (int x = 0; x <= listView1.CheckedItems.Count - 1; x++)
        {
            string tempDirectory = Path.GetTempPath();
            foreach (ListViewItem item in listView1.CheckedItems)
            {
                string fileName = item.Text;
                string filePath = Path.Combine(tempDirectory, fileName);

                try
                {
                    File.Delete(filePath);
                }
                catch (Exception)
                {
                    //ignore files being in use
                }
            }
        }
        PaintListView(tFile);
        MessageBox.Show("Files removed");
        toolStripStatusLabel1.Text = ("Ready");
    }
    else
    {
        MessageBox.Show("Please put a check by the files you want to delete");
    }
}

As Reed mentioned, you cannot access UI elements from a thread other than the UI thread itself. So, you'll have to pass on a delegate Control.Invoke() to be executed with the UI Thread, like this

Try

    private void cleanFiles_DoWork(object sender, DoWorkEventArgs e)
    {
        if (listView1.CheckedItems.Count != 0)
        {
            // If so, loop through all checked files and delete.
            for (int x = 0; x <= listView1.CheckedItems.Count - 1; x++)
            {
                string tempDirectory = Path.GetTempPath();
                foreach (ListViewItem item in listView1.CheckedItems)
                {
                    string fileName = item.Text;
                    string filePath = Path.Combine(tempDirectory, fileName);

                    try
                    {
                        File.Delete(filePath);
                    }
                    catch (Exception)
                    {
                        //ignore files being in use
                    }
                }
            }

            PaintListViewAndSetLabel();
        }
        else
        {
            ShowMessageBox();
        }
    }

    private void ShowMessageBox()
    {
        if(InvokeRequired)
        {
            this.Invoke(new Action(ShowMessageBox), new object[0]);
            return;
        }
        MessageBox.Show("Please put a check by the files you want to delete");
    }

    private void PaintListViewAndSetLabel()
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action(PaintListViewAndSetLabel),new object[0]);
            return;
        }
        PaintListView(tFile);
        MessageBox.Show("Files removed");
        toolStripStatusLabel1.Text = ("Ready");
    }

The problem is that you can't access any properties of your ListView ( listView1 ) from the background thread (ie: anything inside of the cleanFiles_DoWork method) directly. User interface controls can't be accessed on any thread other than the user interface thread.

You should, instead, make a list of the items to "clean" before calling DoWork, and pass these into the method via the RunWorkerAsync overload taking an object , and retrieve it in your method via DoWorkEventArgs.Argument .

This will allow you to pass a list of items to process, process them in the background, then update your list when you are complete.

Its bad idea to use control from background worker, I had the same problem recently with TreeView control. So the solution for Thread-Safe Calls to Windows Forms Controls is How-to article from microsoft. The main idea it checking safty using InvokeRequired property of your control and, if nessesary, run method invocation through Invoke method which is thread safe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM