如何在数据流块中为每个线程创建对象而不是为每个请求创建对象?
How to create object per thread in DataFlow Block but not object per request?
我有一个代码示例
var options = new ExecutionDataflowBlockOptions();
var actionBlock = new ActionBlock<int>(async request=>{
var rand = new Ranodm();
//do some stuff with request by using rand
},options);
此代码的问题在于,在每个请求中我都必须创建新的 rand
对象。有一种方法可以为每个线程定义一个 rand
对象并在处理请求时重复使用同一个对象吗?
感谢 Reed Copsey for the nice article 和 Theodor Zoulias 提醒 ThreadLocal<T>
。
The new ThreadLocal class provides us with a strongly typed,
locally scoped object we can use to setup data that is kept separate
for each thread. This allows us to use data stored per thread,
without having to introduce static variables into our types.
Internally, the ThreadLocal instance will automatically setup the
static data, manage its lifetime, do all of the casting to and from
our specific type. This makes developing much simpler.
// Demonstrates:
// ThreadLocal(T) constructor
// ThreadLocal(T).Value
// One usage of ThreadLocal(T)
static void Main()
{
// Thread-Local variable that yields a name for a thread
ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
{
return "Thread" + Thread.CurrentThread.ManagedThreadId;
});
// Action that prints out ThreadName for the current thread
Action action = () =>
{
// If ThreadName.IsValueCreated is true, it means that we are not the
// first action to run on this thread.
bool repeat = ThreadName.IsValueCreated;
Console.WriteLine("ThreadName = {0} {1}", ThreadName.Value, repeat ? "(repeat)" : "");
};
// Launch eight of them. On 4 cores or less, you should see some repeat ThreadNames
Parallel.Invoke(action, action, action, action, action, action, action, action);
// Dispose when you are done
ThreadName.Dispose();
}
所以你的代码应该是这样的:
ThreadLocal<Random> ThreadName = new ThreadLocal<Random>(() =>
{
return new Random();
});
var options = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 4,
EnsureOrdered = false,
BoundedCapacity = 4 * 8
};
var actionBlock = new ActionBlock<int>(async request =>
{
bool repeat = ThreadName.IsValueCreated;
var random = ThreadName.Value; // your local random class
Console.WriteLine($"Thread: {Thread.CurrentThread.ManagedThreadId},
repeat: ", repeat ? "(repeat)" : "");
}, options);
我有一个代码示例
var options = new ExecutionDataflowBlockOptions();
var actionBlock = new ActionBlock<int>(async request=>{
var rand = new Ranodm();
//do some stuff with request by using rand
},options);
此代码的问题在于,在每个请求中我都必须创建新的 rand
对象。有一种方法可以为每个线程定义一个 rand
对象并在处理请求时重复使用同一个对象吗?
感谢 Reed Copsey for the nice article 和 Theodor Zoulias 提醒 ThreadLocal<T>
。
The new ThreadLocal class provides us with a strongly typed, locally scoped object we can use to setup data that is kept separate for each thread. This allows us to use data stored per thread, without having to introduce static variables into our types. Internally, the ThreadLocal instance will automatically setup the static data, manage its lifetime, do all of the casting to and from our specific type. This makes developing much simpler.
// Demonstrates:
// ThreadLocal(T) constructor
// ThreadLocal(T).Value
// One usage of ThreadLocal(T)
static void Main()
{
// Thread-Local variable that yields a name for a thread
ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
{
return "Thread" + Thread.CurrentThread.ManagedThreadId;
});
// Action that prints out ThreadName for the current thread
Action action = () =>
{
// If ThreadName.IsValueCreated is true, it means that we are not the
// first action to run on this thread.
bool repeat = ThreadName.IsValueCreated;
Console.WriteLine("ThreadName = {0} {1}", ThreadName.Value, repeat ? "(repeat)" : "");
};
// Launch eight of them. On 4 cores or less, you should see some repeat ThreadNames
Parallel.Invoke(action, action, action, action, action, action, action, action);
// Dispose when you are done
ThreadName.Dispose();
}
所以你的代码应该是这样的:
ThreadLocal<Random> ThreadName = new ThreadLocal<Random>(() =>
{
return new Random();
});
var options = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 4,
EnsureOrdered = false,
BoundedCapacity = 4 * 8
};
var actionBlock = new ActionBlock<int>(async request =>
{
bool repeat = ThreadName.IsValueCreated;
var random = ThreadName.Value; // your local random class
Console.WriteLine($"Thread: {Thread.CurrentThread.ManagedThreadId},
repeat: ", repeat ? "(repeat)" : "");
}, options);