Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Renaming

In Java, renaming threads is possible. In .NET it is not. This is because the Name is a property that is write-once in the Thread class:

public string Name
{
    get
    {
        return this.m_Name;
    }
    [HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)]
    set
    {
        lock (this)
        {
            if (this.m_Name != null)
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WriteOnce"));
            }
            this.m_Name = value;
            InformThreadNameChangeEx(this, this.m_Name);
        }
    }
}

Given the fact that Java allows thread renaming and most of the underlying thread structures used are OS-supplied in both platforms, I'm inclined to think that I could actually rename a thread in C#, if I avoid a certain set of functionality that a) I don't care or b) don't use at all.

Do you have any idea why Thread renaming is a write-once operation? Any idea if changing the name breaks something?

I have tried a test where I rename the thread as such:

var t1 = new Thread(TestMethod);
t1.Name = "abc";
t1.Start();
t1.GetType().GetField("m_Name", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(t1, "def");
t1.GetType().GetMethod("InformThreadNameChangeEx", BindingFlags.NonPublic | BindingFlags.Static).Invoke(t1, new object[] { t1, t1.Name});

The result is that the name is indeed changed and this is reflected on other code that uses this thread. The background to this is that I need to log things that threads do and the logging library I use (log4net) uses Thread.Name to specify which thread does what action. Thanks in advance.

EDIT: Please stop suggesting obvious things! I know how to name a thread at start if I am asking how to RE-name it.

The reason why I need to do this, is that the thread will be re-used and it may be used by another component and I want to signify this, if and when there will be logging occuring, so as to have a specific thread name, rather than a generic number.

like image 767
NT_ Avatar asked Jul 28 '10 13:07

NT_


People also ask

How do I rename a thread?

By we can change the name of the thread by using the setName() method. The syntax of setName() and getName() methods are given below: public String getName(): is used to return the name of a thread. public void setName(String name): is used to change the name of a thread.

Can two threads have same name?

Every thread has a name for identification purposes. More than one thread may have the same name. If a name is not specified when a thread is created, a new name is generated for it.

Can we change the name of main thread?

We can set(change) the thread's name by calling the setName method on that thread object. It will change the name of a thread. Example: Java.

Is thread name unique?

Thread names are unique by default. This is by design to be helpful when debugging a program with multiple threads. Log messages can report the thread that is performing a specific step or a debugging can be used to trace a thread with a specific name.


3 Answers

Threads, at the OS level, don't have names. Really, it's just a convenience feature.

like image 135
Steven Sudit Avatar answered Nov 08 '22 08:11

Steven Sudit


I used the analyze operation from Reflector and the only code in the BCL that I saw (or more precisely Nikolaos saw) which uses the Thread.Name getter was a call to the RegisterClassEx API in user32.dll. The Thread class itself only refers to the m_Name member in the Name getter and setter. I suspect it is safe to rename the thread in the manner you have adopted. Except that I would change your code to acquire a lock on the same object that Thread.Name would have. Fortunately that is none other than the Thread instance itself so it is easy to do.

var t1 = new Thread(TestMethod); 
t1.Name = "abc"; 
t1.Start(); 
lock (t1) 
{
  t1.GetType().
      GetField("m_Name", BindingFlags.Instance | BindingFlags.NonPublic).
      SetValue(t1, "def"); 
  t1.GetType().
      GetMethod("InformThreadNameChangeEx", BindingFlags.NonPublic | 
          BindingFlags.Static).
      Invoke(t1, new object[] { t1, t1.Name});
}

Another thing to note is that you might have problems with code access security and changing private members depending on what trust level the application has. Obviously that did not seem to come into play with your test, but it is worth mentioning here.

like image 39
Brian Gideon Avatar answered Nov 08 '22 07:11

Brian Gideon


I would not change the name of the thread in the manner that you are. While you are doing the same thing that a write-many operation would require, you don't know that there aren't behaviors dependent on the operation being write-once.

For example, the debugger, if it gets the thread name, can cache that name, and not have to call the object anymore for it.

There is also a design question here, of why you are depending on the thread name to help with your logging; you are relying on the behavior of the logger to indicate part of the operation you are trying to log.

If you want to capture a certain semantic, you shouldn't shape the logger and the thread to conform to a pattern which will capture that semantic. Instead, explicitly indicate the semantic to the logger at the particular point in time.

like image 4
casperOne Avatar answered Nov 08 '22 07:11

casperOne