internal static IDisposable SetThreadKind(ThreadKinds kind)
{
if ((kind & ThreadKinds.SourceMask) != ThreadKinds.Unknown)
{
throw new InternalException();
}
// Ignore during shutdown.
if (Environment.HasShutdownStarted)
{
return null;
}
ThreadKinds threadKind = CurrentThreadKind;
ThreadKinds source = threadKind & ThreadKinds.SourceMask;
// Special warnings when doing dangerous things on a thread.
if ((threadKind & ThreadKinds.User) != 0 && (kind & ThreadKinds.System) != 0)
{
if (NetEventSource.IsEnabled) NetEventSource.Error(null, "Thread changed from User to System; user's thread shouldn't be hijacked.");
}
if ((threadKind & ThreadKinds.Async) != 0 && (kind & ThreadKinds.Sync) != 0)
{
if (NetEventSource.IsEnabled) NetEventSource.Error(null, "Thread changed from Async to Sync, may block an Async thread.");
}
else if ((threadKind & (ThreadKinds.Other | ThreadKinds.CompletionPort)) == 0 && (kind & ThreadKinds.Sync) != 0)
{
if (NetEventSource.IsEnabled) NetEventSource.Error(null, "Thread from a limited resource changed to Sync, may deadlock or bottleneck.");
}
ThreadKindStack.Push(
(((kind & ThreadKinds.OwnerMask) == 0 ? threadKind : kind) & ThreadKinds.OwnerMask) |
(((kind & ThreadKinds.SyncMask) == 0 ? threadKind : kind) & ThreadKinds.SyncMask) |
(kind & ~(ThreadKinds.OwnerMask | ThreadKinds.SyncMask)) |
source);
if (CurrentThreadKind != threadKind)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Thread becomes:({CurrentThreadKind})");
}
return new ThreadKindFrame();
}