以下代码会出现错误“进程无法访问该文件,因为它正被另一个进程使用”。我很难过,错了。我以管理员身份运行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();
}
}
答案 0 :(得分:3)
问题很可能与您在lambda表达式中捕获循环变量的方式有关。请记住,闭包捕获变量,而不是值。因此,基本上AddDropdownItem
方法可能正在接收参数file
的不同值而不是您认为的值。这是众所周知的closing over the loop variable行为警告。
更改循环,以便将循环变量复制到单独的引用中。
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线程。我会确保在UI线程上创建ComboBoxItem
以获得良好的衡量标准。他们的方式你可能不会引起任何问题,但我会安全地玩。我倾向于中断从UI线程以外的线程到最终极端的无UI元素访问规则。
答案 1 :(得分:1)
我看不到'AddDropDownItem',但我敢打赌你在那里打开文件,而不是在线程完成后关闭文件。解除分配变量(或者让它们超出范围并让GC处理它)是不够的。在线程完成之前先显式关闭文件。