C# - ThreadPool의 스레드는 반환 시 ThreadStatic과 AsyncLocal 값이 초기화 될까요?
뭐, 간단하게 테스트를 하면 알 수 있는 문제입니다. ^^
가령 초기화가 되지 않는다면, 스레드풀의 스레드를 얻어 ThreadStatic 변수를 사용한 다음, 해당 스레드가 풀에 반환된 후 다시 동일한 스레드를 요청해 사용하면 기존의 TLS 값은 유지되고 있을 것입니다. 아래는 이것을 테스트한 코드입니다.
using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(workItem, ewh);
ewh.WaitOne();
ewh.Reset();
}
}
private static void workItem(object state)
{
EventWaitHandle ewh = state as EventWaitHandle;
if (MyType.Text == null)
{
MyType.Text = $"New: " + Environment.CurrentManagedThreadId;
}
else
{
MyType.Text = $"Old: " + MyType.Text;
}
Console.WriteLine($"{Environment.CurrentManagedThreadId}: {MyType.Text}");
ewh.Set();
}
}
class MyType
{
[ThreadStatic]
public static string Text;
}
/* 출력 결과
3: New: 3
4: New: 4
4: Old: New: 4
4: Old: Old: New: 4
5: New: 5
6: New: 6
4: Old: Old: Old: New: 4
3: Old: New: 3
3: Old: Old: New: 3
6: Old: New: 6
*/
출력을 보면 알 수 있듯이, 동일한 스레드가 사용된 경우 기존의 TLS 값이 그대로 살아 있는 것을 확인할 수 있습니다. (Task도 마찬가지로 어차피 같은 스레드풀을 사용하므로 TLS 재사용은 같습니다.)
그렇다면
AsyncLocal은 어떨까요?
HttpContextAccessor를 통해 이해하는 AsyncLocal<T>
; https://www.sysnet.pe.kr/2/0/12467
역시 유사한 코드로 테스트를 해보면 됩니다.
using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(workItem, ewh);
ewh.WaitOne();
ewh.Reset();
}
}
private static void workItem(object state)
{
EventWaitHandle ewh = state as EventWaitHandle;
if (MyType.Text.Value == null)
{
MyType.Text.Value = $"New: " + Environment.CurrentManagedThreadId;
}
else
{
MyType.Text.Value = $"Old: " + MyType.Text.Value;
}
Console.WriteLine($"{Environment.CurrentManagedThreadId}: {MyType.Text.Value}");
ewh.Set();
}
}
class MyType
{
public static AsyncLocal<string> Text = new AsyncLocal<string>();
}
/* 출력 결과
3: New: 3
3: New: 3
3: New: 3
3: New: 3
6: New: 6
6: New: 6
6: New: 6
5: New: 5
5: New: 5
5: New: 5
*/
보는 바와 같이, AsyncLocal의 경우 스레드풀에 반환 시 또는 또는 얻는 시점 둘 중의 한순간에는 초기화가 되었을 거라는 짐작을 할 수 있습니다. ^^
(
첨부 파일은 이 글의 예제 코드를 포함합니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]