Проблема многопоточности с listView - PullRequest
0 голосов
/ 11 апреля 2011

Хорошо, прежде чем каждый публикует дубликат, позвольте мне сообщить вам, что я просмотрел все эти другие посты, и я все еще потерял некоторые, скажем, использование делегатов или фонового работника и т. Д. ... но как я могу сделать эту тему безопасной, я хочу удалить файлысвоя нить.

вот код, с которым я работаю.

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

Ответы [ 3 ]

2 голосов
/ 11 апреля 2011

Как упоминал Рид, вы не можете получить доступ к элементам пользовательского интерфейса из потока, отличного от самого потока пользовательского интерфейса. Таким образом, вам нужно будет передать делегат Control.Invoke() для выполнения с потоком пользовательского интерфейса, например,

Попробуйте

    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");
    }
0 голосов
/ 11 апреля 2011

Это плохая идея использовать элемент управления из фонового приложения, у меня недавно была такая же проблема с элементом управления TreeView. Таким образом, решение для поточно-ориентированных вызовов к элементам управления Windows Forms - Статья с инструкциями от Microsoft. Основная идея - проверка безопасности с использованием свойства InvokeRequired вашего элемента управления и, если необходимо, запуск вызова метода через метод Invoke, который является поточно-ориентированным.

0 голосов
/ 11 апреля 2011

Проблема в том, что вы не можете получить доступ к каким-либо свойствам вашего ListView (listView1) напрямую из фонового потока (т. Е. К чему-либо внутри метода cleanFiles_DoWork).Элементы управления пользовательского интерфейса не могут быть доступны в любом потоке, кроме потока пользовательского интерфейса.

Вместо этого вы должны составить список элементов, которые нужно «очистить» перед вызовом DoWork, и передать их в метод черезперегрузка RunWorkerAsync, принимающая объект и извлекающая его в вашем методе через DoWorkEventArgs.Argument .

Это позволит вам передать список элементов для обработки, обработать их в фоновом режиме, а затем обновить список по завершении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...