2014-02-07 2 views
0

스레드와 함께 작업 한 것은 처음이므로 Thread.CurrentThread.Name의 값이 null 인 이유가 무엇인지 혼동합니다. 각각의 특정 스레드가 자체의 타이머를 갖기를 원하고 각 스레드가 실행 중인지 먼저 테스트하고 싶습니다. OnElapsed 메소드. 그러나 Visual Studio를 사용하여 디버깅 할 때 스레드 이름이 null 인 것 같습니다. 어떤 도움을 주시면 감사하겠습니다.왜 스레드 이름이 null입니까?

public class Sample { 

    static System.Timers.Timer myTimer = new System.Timers.Timer(); 
    static int i = 0; 
    public static void Main() 
    { 
    FileSystemWatcher watcher = new FileSystemWatcher(); 
    watcher.Path = @"C:\Users\Documents"; 

    watcher.NotifyFilter = NotifyFilters.LastWrite; 
    Thread.CurrentThread.Name = "main"; 

    watcher.Filter = "*.txt"; 

    watcher.Changed += new FileSystemEventHandler(OnChanged); 
    watcher.EnableRaisingEvents = true; 
    Console.WriteLine("Press the Enter key to exit the program."); 
    Console.ReadLine(); 

} 

private static void OnElapsed(object source, ElapsedEventArgs e) 
{ 
    Console.WriteLine(Thread.CurrentThread.Name); //<-- why is this null? 
    myTimer.Enabled = false; 
    Console.WriteLine(e.SignalTime); 
} 

private static void OnChanged(object source, FileSystemEventArgs e) 
{ 

     FileSystemWatcher t = source as FileSystemWatcher; 
     t.EnableRaisingEvents = false; 
     string path = e.FullPath;  
     Thread t1 = new Thread(() => Print(path)); 
     t1.Name = "Thread " + i; 
        i++; 
     t1.IsBackground = true; 
     t1.Start(); 
     t.EnableRaisingEvents = true; 

} 

static void Print(string source) 
{ 

      string xmlFilePath = "xmlBasic.xml"; 
      string timeout; 
      string path = Path.GetDirectoryName(source); 
      List<string> wordList = new List<string>(); 

      XmlDocument doc = new XmlDocument(); 
      doc.Load(xmlFilePath);   
      XmlNode timeouts; 
      XmlElement root = doc.DocumentElement; 
timeouts = root.SelectSingleNode("descendant::paths[directory='" + path + "']"); 

      timeout = timeouts.LastChild.InnerText; 
      myTimer.Interval = int.Parse(timeout); 
      myTimer.Elapsed += new ElapsedEventHandler(OnElapsed); 
      myTimer.Enabled = true; 

} 
} 

미리 감사드립니다.

+5

내가이 일에 대해 잘 모르는입니다하지만 난 궁금 당신이 기대하는 가치는 무엇입니까? 보시다시피 메인 스레드의 이름을 지정하고 있지만 이벤트 발생에 의해 스핀 업되는 스레드는 아무 것도 명시 적으로 지정되지 않습니다 ... – Chris

+0

System.Timers.Timer는 Elapsed 이벤트를 다른 스레드에서 발생시키기 때문에 (분명히?) 스레드 이름을 설정 한 곳이 아닙니다. –

답변

1

우리가

SynchronizingObject의 속성이 null의 경우, 경과 이벤트가 스레드 풀 스레드에서 제기 입니다 다음 우리가 볼 수있는 Timer.Elapsed Event documentation 보면. Elapsed 이벤트 의 처리가 Interval보다 오래 지속되면 다른 ThreadPool 스레드에서 이벤트가 다시 발생할 수 있습니다. 이 경우 이벤트 처리기는 재진입 성이어야합니다.

즉, 이벤트를 발생시키는 스레드는 스레드 풀에서 나오며 사용자가 지정한 스레드가 아닙니다.

당신이 정말로 그것을 지정된 스레드를해야 할 경우 여기에 예를 들어 ISynchronizeInvoke를 구현하는 객체를 만들어야합니다는 존 소총에 의한 implementation

0

FileSystemEventHandler가 OnElapsed 이벤트를 처리 할 때이 이벤트는 메인의 동일한 스레드에서 실행되지 않기 때문에 null입니다.

다음 예제를 실행하면 Changed 이벤트 처리기가 다른 스레드에서 실행된다는 것을 알 수 있습니다.

public static void Main(string[] args) 
{ 
    Directory.CreateDirectory("dir1"); 
    Directory.CreateDirectory("dir2"); 
    Directory.CreateDirectory("dir3"); 

    Console.WriteLine("Main Thread Id: {0}", 
     Thread.CurrentThread.ManagedThreadId); 

    const int watcherCount = 3; 
    string[] dirs = new string[] { "dir1", "dir2", "dir3" }; 

    for (int i = 0; i < watcherCount; i++) 
    { 
     var watcher = new FileSystemWatcher(); 
     watcher.Path = dirs[i]; 
     watcher.Changed += (sender, e) => 
     { 
      Console.WriteLine("File: {0} | Thread: {1}", e.Name, 
       Thread.CurrentThread.ManagedThreadId); 

      Thread.Sleep(2000); // Simulate long operation 
     }; 
     watcher.EnableRaisingEvents = true; 
    } 

    File.WriteAllText(@"dir1\test1", "hello"); 
    File.WriteAllText(@"dir2\test2", "hello"); 
    File.WriteAllText(@"dir3\test3", "hello"); 

    Thread.Sleep(10000); 
}