2013-06-13 15 views
11

C#(.NET)では、同じアプリケーションで実行されている2つのスレッドが異なる "WorkingFolders"を持つことができますか?C#マルチスレッドアプリケーションはスレッドごとに作業ディレクトリを使用できますか?

わかりやすく、答えは「いいえ」です。私はWORKING DIRがWin32のPROCESSによって設定されていると思います...私は間違っていますか?

次のテストコード(Win32 SetCurrentDirectory API呼び出し)によれば、これは不可能ですが、誰かが可能にする方法を考え出していますか?

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

私は知っている誰かがこれまでに実行したことがあります!

+5

これを試みる目的は何ですか?通常、適切なフォルダを渡すためにコードを設計するほうがよいでしょう。 –

+0

スレッドごとに別々のアプリケーションドメインを作成している可能性があります。私は現在、例を示すことができないので、これをコメントとして追加しました。 – MarcF

+1

@MarcF Appドメインは、プロセスごとに1つの環境セット(FYI)を変更しません。 –

答えて

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を参照することができます。例えば:あなたは、もちろん、そのファイルIOを扱うときは常にそのパスを修飾する必要があります

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

、しかしこれはとにかく間違いなく、より安全な設計です。

+0

異なる 'AppDomain'を作成し、そこに' AppDomainSetup.PrivateBinPath'を設定するのはどうですか?そうすれば、彼は何とかそれを「設定」することができます。おそらく私は間違っています – Odys

+1

ここでの目標は、 'File.Open(" Foo.txt ")'を別のスレッドで別々に動作させることでした。答えはいいえ、あなたはそれをすることはできませんし、それをやろうとしているべきでもありません。 –

3

誰もがそれを可能にする方法を考え出しましたか?

これは単純にではありません。です。 App Domainごとに異なる作業ディレクトリを持つことさえできません。

ウィンドウルールは、プロセスごとに1つの環境セットです。 .NETで実行しても、基本ルールは変更されません。

アセンブリの読み込みで問題が発生した場合は、対応するフォルダをPATH環境変数に追加することを検討してください。

+0

ありがとうエリック、これは私が疑っていたことですが、私はこれまでのところ、Mike Christensenが最善の答えを持っていると思います...これにより、CurrentDir + Passed Path/FileをIO関数にハードコードし、探しています。しかし、Win32のドキュメントのために、私は恐れていました。 – LarryF

関連する問題