Joshua Frank
Joshua Frank

Reputation: 13838

How to set the thread name twice?

In my app, I want to name the thread performed by a task using a name relevant to that task, so I can keep the the threads straight. So I use code like

Threading.Thread.CurrentThread.Name = this.GetType().Name;

where this is a class that's dedicated to that task, like class FilePurgeTask {...}

The problem is that a thread can be reused with a different class in scope, so the name would then be wrong. And if I try to reset the name, it fails with System.InvalidOperationException ...This property has already been set and cannot be modified

Indeed, the docs say "This property is write-once.".

Is there any way to work around it?

Upvotes: 1

Views: 346

Answers (2)

PMF
PMF

Reputation: 17185

The documentation is outdated.

This limitation was removed in .NET 6.0, but apparently the documentation has not been updated. In .NET 5.0, the Name property is implemented as:

        public string? Name
        {
            get => _name;
            set
            {
                lock (this)
                {
                    if (_name != null)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_WriteOnce);
                    }

                    _name = value;

                    ThreadNameChanged(value);
                }
            }
        }

while in .NET 6.0, this is simply changed to:

        public string? Name
        {
            get => _name;
            set
            {
                lock (this)
                {
                    if (_name != value)
                    {
                        _name = value;
                        ThreadNameChanged(value);
                        _mayNeedResetForThreadPool = true;
                    }
                }
            }
        }

This simple test works fine when running under .NET 6.0, and the debugger correctly displays changing thread names when single-stepping:

        [Fact]
        public void NameThread()
        {
            Thread.CurrentThread.Name = "Blah";
            Thread.CurrentThread.Name = "Fasel";
        }

So, the "workaround" is to upgrade to .NET 6.0 ;-)

Upvotes: 1

John Glenn
John Glenn

Reputation: 1629

You could use a thread-safe ConcurrentDictionary to store the thread ID (key) and the operation it is performing (value). Using the Thread.Name property won't support the dynamical, reassignable tagging you are looking for.

For what it's worth, the Name property will be null unless it has been set, so you could simply wrap your code in a null check like so to avoid throwing an exception:

if(Thread.CurrentThread.Name == null)
{
    Thread.CurrentThread.Name = this.GetType().Name;
}

Upvotes: 0

Related Questions