listView 的跨线程问题

发布于 2024-10-31 18:46:45 字数 1212 浏览 1 评论 0 原文

好的,在每个人发布重复之前,让我通知您我已经查看了所有其他帖子,但我仍然丢失了一些说使用委托或后台工作人员等的内容...但是我如何使该线程安全我想删除其自己线程上的文件。

这是我正在使用的代码。

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");
    }
}

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");
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无名指的心愿 2024-11-07 18:46:45

正如 Reed 提到的,您无法从 UI 线程本身以外的线程访问 UI 元素。因此,您必须传递一个委托 Control.Invoke() 才能使用 UI 线程执行,如下

所示

    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");
    }

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");
    }
热鲨 2024-11-07 18:46:45

问题是您无法直接从后台线程访问 ListView (listView1) 的任何属性(即:cleanFiles_DoWork 方法内的任何内容)。无法在用户界面线程以外的任何线程上访问用户界面控件。

相反,您应该在调用 DoWork 之前列出要“清理”的项目列表,并通过 RunWorkerAsync 重载获取一个对象,并通过 DoWorkEventArgs.Argument

这将允许您传递要处理的项目列表,在后台处理它们,然后在完成后更新您的列表。

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.

梦亿 2024-11-07 18:46:45

使用后台工作者的控件是个坏主意,我最近在使用 TreeView 控件时遇到了同样的问题。因此,线程安全调用 Windows 窗体控件的解决方案是 来自 Microsoft 的操作方法文章。主要思想是使用控件的 InvokeRequired 属性检查安全性,如果需要,通过线程安全的 Invoke 方法运行方法调用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文