为什么线程名称为null?

时间:2014-02-07 16:37:50

标签: c# multithreading timer

这是我第一次使用线程,所以我真的很困惑为什么Thread.CurrentThread.Name包含值null。我希望每个特定的线程都有自己的计时器,并希望首先测试每个线程是否正在执行OnElapsed方法。但是,当我使用Visual Studio调试它时,线程名称似乎是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;

 }
}

提前致谢!

2 个答案:

答案 0 :(得分:1)

如果我们查看Timer.Elapsed Event documentation,我们会看到以下内容

  

如果SynchronizingObject属性为null,则Elapsed事件为   在ThreadPool线程上引发。如果处理了Elapsed事件   持续时间超过Interval,事件可能会再次提升   ThreadPool线程。在这种情况下,事件处理程序应该是   折返。

这意味着引发事件的线程来自线程池,而不是您命名的线程。

如果你真的需要让它成为一个指定的线程,你将不得不创建一个实现ISynchronizeInvoke的对象,例如这里是Jon Skeet的implementation

答案 1 :(得分:0)

它为null因为当FileSystemEventHandler处理OnElapsed事件时,它不会在main的同一个线程上运行。

如果运行以下示例,您将看到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);
}