c#线程访问问题

c#线程访问问题,c#,multithreading,C#,Multithreading,下面的代码出现错误“该进程无法访问该文件,因为它正被另一个进程使用”。我不知道出了什么问题。我以管理员身份运行VisualStudio,并且在记事本中打开了其中的非文件 private void Load_Click(object sender, RoutedEventArgs e) { if (txtInput.Text.Length > 1) { //var rootDir = System.IO.Directory.GetCur

下面的代码出现错误“该进程无法访问该文件,因为它正被另一个进程使用”。我不知道出了什么问题。我以管理员身份运行VisualStudio,并且在记事本中打开了其中的非文件

    private void Load_Click(object sender, RoutedEventArgs e)
    {
        if (txtInput.Text.Length > 1) {
            //var rootDir = System.IO.Directory.GetCurrentDirectory();
            string rootDir = @"C:\b";
            string search = txtInput.Text.Replace(" ", "");
            List<Thread> searches = new List<Thread>();

            foreach (var file in new DirectoryInfo(rootDir).GetFiles().Where(z => z.LastWriteTime > DateTime.Now.AddDays(-7))) {
                if (file.ToString().Contains(".log")) {
                    searches.Add(new Thread(new ThreadStart(() => AddDropdownItem(file.ToString(),search))));
                }
            }
            //Run ten threads at a time and wait for them to finish
            for (int i = 0; i < searches.Count; i = i + 10) {
                List<Thread> pool = new List<Thread>();
                for (int j = 0; j < 10; j++) {
                    if (i + j < searches.Count) {
                        Thread t = searches[(i + j)];
                        pool.Add(t);
                    }
                }

                foreach (Thread t in pool) {
                    t.Start();
                }

                foreach (Thread t in pool) {
                    t.Join();
                }
            }
        }
    }

    private void AddDropdownItem(string file, string search)
    {
        if (GetFileContent(file.ToString()).Contains(search)) {
            ComboBoxItem item = new ComboBoxItem();
            item.Content = file.ToString();
            Dispatcher.BeginInvoke(new ThreadStart(() => ddFiles.Items.Add(item)));
        }
    }

    private string GetFileContent(string file)
    {
        string path = System.IO.Path.Combine(@"C:\b", file);
        using (FileStream fs = new FileStream(path, FileMode.Open)) {
            return new StreamReader(fs).ReadToEnd();
        }
    }
private void Load\u单击(对象发送方,路由目标)
{
如果(txtInput.Text.Length>1){
//var rootDir=System.IO.Directory.GetCurrentDirectory();
字符串rootDir=@“C:\b”;
字符串搜索=txtInput.Text.Replace(“,”);
列表搜索=新建列表();
foreach(新目录信息(rootDir.GetFiles().Where(z=>z.LastWriteTime>DateTime.Now.AddDays(-7))中的var文件){
if(file.ToString()包含(“.log”)){
searches.Add(新线程(新线程开始(()=>AddDropdownItem(file.ToString(),search)));
}
}
//一次运行十个线程并等待它们完成
for(int i=0;iddFiles.Items.Add(item));
}
}
私有字符串GetFileContent(字符串文件)
{
字符串路径=System.IO.path.Combine(@“C:\b”,文件);
使用(FileStream fs=newfilestream(路径,FileMode.Open)){
返回新的StreamReader(fs).ReadToEnd();
}
}

我看不到“AddDropDownItem”,但我敢打赌,线程处理完文件后,您正在打开文件,而不是关闭文件。取消分配变量(或者仅仅让它们脱离范围并让GC处理)是不够的。在线程结束之前先显式关闭文件。

问题最有可能是在lambda表达式中捕获循环变量的方式。记住,闭包捕获的是变量,而不是值。因此,基本上,
AddDropdownItem
方法接收到的参数
file
的值可能与您认为的不同。这是一个众所周知的行为警告

更改循环,以便将循环变量复制到单独的引用中

foreach (var file in new DirectoryInfo(rootDir).GetFiles().Where(z => z.LastWriteTime > DateTime.Now.AddDays(-7))) 
{
  if (file.ToString().Contains(".log")) 
  {
    var capture = file;
    searches.Add(new Thread(new ThreadStart(() => AddDropdownItem(capture.ToString(),search))));
  }
}

我注意到一个潜在的无关问题。看起来您正在从一个工作线程创建一个
ComboBoxItem
。我确实看到您正在将add操作封送到UI线程。我会确保在UI线程上也创建了
ComboBoxItem
,以便更好地度量。他们的方式你可能不会引起任何问题,但我会谨慎行事。我倾向于中断从UI线程以外的线程不访问UI元素的规则,直至其极限。

+1作为对未注释DownVote的支持,为什么要对字符串调用.ToString()?所有代码都在上面的示例中。我将文件流放在一个using块中。我也尝试过显式关闭它,但它没有帮助您是否在其他地方打开任何其他文件?这太完美了!您的第一个答案解决了我的问题,然后第二个解决了我在开始工作时发现的另一个bug。非常感激