簡體   English   中英

c#線程訪問問題

[英]c# threading access problem

下面的代碼會出現錯誤“進程無法訪問該文件,因為它正被另一個進程使用”。 我很難過,錯了。 我以管理員身份運行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();
        }
    }

問題很可能與您在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 我確實看到你正在編組添加操作到UI線程。 我會確保ComboBoxItem也是在UI線程上創建的,以便進行測量。 他們的方式你可能不會引起任何問題,但我會安全地玩。 我傾向於中斷從UI線程以外的線程到其最終極端的無UI元素訪問規則。

我看不到'AddDropDownItem',但我敢打賭你在那里打開文件,而不是在線程完成后關閉文件。 解除分配變量(或者讓它們超出范圍並讓GC處理它)是不夠的。 在線程完成之前首先顯式關閉文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM