简体   繁体   English

c#线程访问问题

[英]c# threading access problem

The below code falls over with the error "The process cannot access the file because it is being used by another process". 下面的代码会出现错误“进程无法访问该文件,因为它正被另一个进程使用”。 Im stumped as to whats wrong. 我很难过,错了。 Im running visual studio as administrator and non of the files are open in notepad . 我以管理员身份运行visual studio,而非文件在记事本中打开。

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

The problem is most likely with the way you are capturing the loop variable in the lambda expression. 问题很可能与您在lambda表达式中捕获循环变量的方式有关。 Remember, closures capture the variable , not the value . 请记住,闭包捕获变量 ,而不是 So basically the AddDropdownItem method may be receiving a different value for the parameter file than what you think it is. 因此,基本上AddDropdownItem方法可能正在接收参数file的不同值,而不是您的想法。 This is a well known behavioral caveat with closing over the loop variable . 这是一个众所周知的行为警告, 关闭了循环变量

Change the loop so that you copy the loop variable into a separate reference. 更改循环,以便将循环变量复制到单独的引用中。

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

I noticed a potential unrelated problem. 我注意到一个潜在的无关问题。 It appears that you are creating a ComboBoxItem from one of your worker threads. 您似乎正在从一个工作线程创建一个ComboBoxItem I do see that you are marshaling add operation onto the UI thread. 我确实看到你正在编组添加操作到UI线程。 I would make sure that the ComboBoxItem is also created on the UI thread for good measure. 我会确保ComboBoxItem也是在UI线程上创建的,以便进行测量。 They way you have it probably will not cause any issues, but I would play it safe. 他们的方式你可能不会引起任何问题,但我会安全地玩。 I tend to interrupt the rule of no UI element access from a thread other than the UI thread to its ultimate extreme. 我倾向于中断从UI线程以外的线程到其最终极端的无UI元素访问规则。

I can't see the 'AddDropDownItem' but I'll bet you're opening the file in there and not closing the files when the thread is done with them. 我看不到'AddDropDownItem',但我敢打赌你在那里打开文件,而不是在线程完成后关闭文件。 Deallocating the variables(or just letting them fall out of scope and letting the GC handle it) isn't enough. 解除分配变量(或者让它们超出范围并让GC处理它)是不够的。 Explicitly close the files first before the thread finishes. 在线程完成之前首先显式关闭文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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