12

在 C# (.NET) 中,在同一个应用程序中运行的两个线程可以有不同的“WorkingFolders”吗?

据我所知,答案是“不”。我认为 WORKING DIR 是由 Win32 中的 PROCESS 设置的。我在这里错了吗?

根据以下测试代码(以及 Win32 SetCurrentDirectoryAPI 调用),这是不可能的,但有没有人想出办法让它成为可能?

using System;
using System.Threading;

public class TestClass {

  public  ManualResetEvent _ThreadDone = new ManualResetEvent(false);

  public static void Main() {
    Console.WriteLine(Environment.CurrentDirectory);

    Thread _Thread = new Thread(new ParameterizedThreadStart(Go));
    TestClass test = new TestClass();

    _Thread.Start(test);
    if(test._ThreadDone.WaitOne()) {
      Console.WriteLine("Thread done.  Checking Working Dir...");
      Console.WriteLine(Environment.CurrentDirectory);
    }
  }

  public static void Go(object instance) {
    TestClass m_Test = instance as TestClass;
    Console.WriteLine(Environment.CurrentDirectory);
    System.IO.Directory.SetCurrentDirectory("L:\\Projects\\");
    Console.WriteLine(Environment.CurrentDirectory);
    m_Test._ThreadDone.Set();
  }
}

我知道外面一定有人遇到过这个!

4

2 回答 2

9

我猜你想要做的是让代码File.Open("Foo.txt")在不同的线程上表现不同。你能做这个吗?简短的回答是否定的——你也不应该尝试这样做。在 Windows 上,当前工作目录设置在进程级别。.NET 框架不违反该规则。

更好的方法是在其之上创建一个Environment.CurrentDirectory特定于线程的抽象。就像是:

public static class ThreadEnvironment
{
   [ThreadStatic]
   static string _currentDir;

   public static string CurrentDirectory
   {
      get
      {
         if (_currentDir == null) // If Current Directory has not been set on this thread yet, set it to the process default
         {
            _currentDir = Environment.CurrentDirectory;
         }

         return _currentDir;
      }

      set
      {
         if (value == null)
            throw new ArgumentException("Cannot set Current Directory to null.");

         _currentDir = value;
      }
   }
}

然后您可以参考ThreadEnvironment.CurrentDirectory获取该线程的当前目录,如果尚未在该线程上设置它,它将默认为进程目录。例如:

static void Main(string[] args)
{
   (new Thread(Thread1)).Start();
   (new Thread(Thread2)).Start();
}

static void Thread1()
{
   Console.WriteLine("Thread1 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
   ThreadEnvironment.CurrentDirectory = @"C:\";
   Console.WriteLine("Thread1 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
}

static void Thread2()
{
   Console.WriteLine("Thread2 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
   ThreadEnvironment.CurrentDirectory = @"C:\Windows";
   Console.WriteLine("Thread2 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
}

当然,您需要在处理文件 IO 时限定该路径,但是无论如何这可以说是一种更安全的设计。

于 2013-06-13T22:37:53.480 回答
4

有没有人想出办法让它成为可能?

这根本不可能。每个应用程序域甚至不能有不同的工作目录。

Windows 规则是:每个进程设置一个环境。在 .NET 中运行不会改变基本规则。

相反,如果您在加载程序集时遇到问题,请考虑将相应的文件夹添加到 PATH 环境变量中。

于 2013-06-13T22:36:54.727 回答