2011-04-11 42 views
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"); 
    } 
} 

回答

0

的问题是,你不能(即:cleanFiles_DoWork方法里面的任何东西)从后台线程访问的ListView(listView1)的任何属性直接。在用户界面线程以外的任何线程上都无法访问用户界面控件。

相反,您应该在调用DoWork之前将项目列表设置为“干净”,然后通过RunWorkerAsync overload taking an object将这些项目传递给方法,并通过DoWorkEventArgs.Argument在您的方法中检索它。

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

+0

请给我一个例子以上面我的代码? – partialdata 2011-04-11 20:23:29

+0

你谈论制作一个列表,是否有一种方法,当项目被选中时,它会将该文件添加到数组的路径中?那么当你打到干净的时候,它会将该数组列表发送到干净的文件方法,然后启动一个线程并删除这些文件? – partialdata 2011-04-11 20:49:46

2

正如里德所说,你不能从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"); 
    } 
+0

谢谢你的帮助!我正在处理所有的信息! ;] 大声笑 ! – partialdata 2011-04-11 19:09:06

+0

我试过上面的代码相同的问题做它在if(listView1.CheckedItems.Count!= 0)怪胎我需要移出背景工作者,只使用线程吗? – partialdata 2011-04-11 19:26:57

+0

通常从视图中获取某些内容应该没问题;它只是设置需要调用'Invoke()'的东西 – 2011-04-11 19:29:18

0

它的坏主意,使用从后台辅助控制,最近我有同样的问题与TreeView控件。因此,针对Windows窗体控件的线程安全调用解决方案来自Microsoft的How-to article。它使用你的控件的InvokeRequired属性来检查安全性的主要思想,并且如果存在的话,通过Invoke方法调用线程安全的方法。