2

This is my first time working with threads, so I am really confused as to why the Thread.CurrentThread.Name contains a value of null. I want each specific thread to have a timer of its own, and wanted to first test if each thread is executing the OnElapsed method. However, the thread name seems to be null when I debugged it using Visual Studio. Any help would be appreciated.

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;

 }
}

Thanks in advance!

Kristof U.
  • 1,263
  • 10
  • 17
TestNInja
  • 177
  • 2
  • 15
  • 5
    I don't know much about these things but I'm curious what value you expect it to have? As I see it you are naming your main thread but any threads spun up by events firing will not be named anything explicit... – Chris Feb 07 '14 at 16:39
  • Because System.Timers.Timer will raise (obviously?) Elapsed event in another thread. Not in the one it has been created (where you set thread name). – Adriano Repetti Feb 07 '14 at 16:42

2 Answers2

1

If we look at the Timer.Elapsed Event documentation we see the following

If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread. If the processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.

This means that the thread that raises the event comes from the threadpool and won't be the one that you named.

If you really need to make it a specified thread you'll have to create an object that implements ISynchronizeInvoke for example here's an implementation by Jon Skeet

Community
  • 1
  • 1
Conrad Frix
  • 51,984
  • 12
  • 96
  • 155
0

Its null because when the FileSystemEventHandler handle the OnElapsed event, this is not running on the same thread of main.

If you run the following example you will see that the Changed event handler will run in a different thread.

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);
}
Only a Curious Mind
  • 2,807
  • 23
  • 39