Ребята,
Допустим, я сохраняю три новых экземпляра объекта Car с помощью CallContext.SetData () из потока 10, 11, 12. Эти потоки завершают выполнение. Затем я выполняю другую многопоточную операцию (возможно, отличную от первой), в которой используются потоки 10, 11, 12. Будет ли GetData () извлекать те же три объекта, которые я сохранил? Или контекст как-то изменился, и эти объекты исчезли?
Мой конкретный вариант использования - это параллельная библиотека задач. Я использую TPL для распараллеливания некоторых операций и хочу понять, что происходит с данными, хранящимися через CallContext.SetData () между вызовами TPL.
EDIT
Согласно предложению @wageoghe, я попробовал ThreadLocal, и он сработал!
обновленный код, чтобы доказать это:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TlsTest
{
public class Program
{
public static void Main()
{
Console.WriteLine( "-------using threadpool---------" );
UseThreadPool();
Console.WriteLine( "-------using tasks---------" );
UseTasks();
Console.WriteLine( "-------using parallel for---------" );
UseParallelFor();
Console.ReadKey();
}
public static void UseThreadPool()
{
var finish = new CountdownEvent( TotalThreads );
for ( int i = 0 ; i < TotalThreads ; i++ )
{
ThreadPool.QueueUserWorkItem( x =>
{
int id = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep( SleepMilliseconds );
if ( ThreadId.IsValueCreated )
{
Console.WriteLine( "thread [{0}], tls.thread [{1}] - value already in Tls" , id , ThreadId.Value );
}
else
{
Console.WriteLine( "thread [{0}] - no Tls value" , id );
ThreadId.Value = id;
}
Thread.Sleep( SleepMilliseconds );
finish.Signal();
} );
}
finish.Wait();
}
public static void UseTasks()
{
const TaskCreationOptions taskCreationOpt = TaskCreationOptions.None;
var allTasks = new Task[ TotalThreads ];
for ( int i = 0 ; i < TotalThreads ; i++ )
{
Task task = Task.Factory.StartNew( () =>
{
int id = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep( SleepMilliseconds );
if ( ThreadId.IsValueCreated )
{
Console.WriteLine( "thread [{0}], tls.thread [{1}] - value already in Tls" , id , ThreadId.Value );
}
else
{
Console.WriteLine( "thread [{0}] - no Tls value" , id );
ThreadId.Value = id;
}
Thread.Sleep( SleepMilliseconds );
} , taskCreationOpt );
allTasks[ i ] = task;
}
Task.WaitAll( allTasks );
}
public static void UseParallelFor()
{
var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 8;
Parallel.For( 0 , TotalThreads , options , i =>
{
int id = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep( SleepMilliseconds );
if ( ThreadId.IsValueCreated )
{
Console.WriteLine( "thread [{0}], tls.thread [{1}] - value already in Tls" , id , ThreadId.Value );
}
else
{
Console.WriteLine( "thread [{0}] - no Tls value" , id );
ThreadId.Value = id;
}
Thread.Sleep( SleepMilliseconds );
} );
}
private static readonly ThreadLocal<int> ThreadId = new ThreadLocal<int>();
private const int TotalThreads = 100;
private const int SleepMilliseconds = 500;
}
}