If I have a Parallel.ForEach like this using a anonymous delegate for the main loop of the ForEach:
var someState = GetSomeState();
Parallel.ForEach(MyIEnumerableSource,
() =>
{
return new DataTable();
},
(record, loopState, localDataTable) =>
{
localDataTable.Rows.Add(someState.Value, record);
return localDataTable
},
(localDataTable) =>
{
using (var bulkInsert = new SqlBulkCopy(ConnectionString))
{
bulkInsert.DestinationTableName = "My_Table";
bulkInsert.WriteToServer(localDataTable);
}
localDataTable.Dispose();
});
How can I turn it in to the following where the main loop is now a real function but is static sitting in another class:
var someState = GetSomeState();
Parallel.ForEach(MyIEnumerableSource,
() =>
{
return new DataTable();
},
OtherClass.Process,
(localDataTable) =>
{
using (var bulkInsert = new SqlBulkCopy(ConnectionString))
{
bulkInsert.DestinationTableName = "My_Table";
bulkInsert.WriteToServer(localDataTable);
}
localDataTable.Dispose();
});
//In another class in another file
static class OtherClass
{
public static DataTable Process(MyRecordType record, ParallelLoopState loopState, DataTable localDataTable)
{
localDataTable.Rows.Add(someState.Value, record); //How to I bring over someState when it is called here?
return localDataTable
}
}
How I can access that state that is created outside of the for loop and does not need to be part of the thread local storage?
I would just use a instance variable if this function was not static and resided in the same class but the main loop of the ForEach is in a static function in another class and will be used from multiple locations in the code, all with their own different copy of someState.
How do I bring that state variable along?
Short answer: Call it from an anonymous method.
You can pass your additional state as separate parameter from the anonymous method.
For example:
var someState = GetSomeState();
Parallel.ForEach(MyIEnumerableSource,
() => new DataTable(),
(record, loopState, localDataTable) =>
OtherClass.Process(record, loopState, LocalDataTable, someState),
(localDataTable) => { ... }
);
static class OtherClass
{
public static DataTable Process(MyRecordType record, ParallelLoopState loopState, DataTable localDataTable, someStateType someState)
{
localDataTable.Rows.Add(someState.Value, record);
return localDataTable
}
}
Long answer: Make a separate class that holds the state, and put the method in that class. You can then pass the instance method, and it will have access to the state from the class that holds it.
This is how anonymous methods are compiled.
For a more thorough explanation, see my blog.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With