I have a class of range
public class avl_range
{
public long start { get; set; }
public long end { get; set; }
}
If I use a normal
Even if you could get it to work with MARS, connection objects are almost never thread safe anyway, you need to have a connection per thread. Parallel.ForEach has overloads to make this easy which have functions that run at the start of a thread and at the end.
var numbers = new List();
Func localInit => () =>
{
var conn = new NpgsqlConnection(strConnection);
conn.Open();
};
Action localFinally = (conn) => conn.Dispose();
Func forEachLoop = (number, loopState, conn) => //Begin definition of forLoop
{
// only the console write line works ok
Console.WriteLine(number.start + " - " + number.end);
using (var cmd = new NpgsqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = String.Format( "SELECT * FROM avl_db.process_near_link({0}, {1});"
, number.start
, number.end);
// here cause the error.
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
}
}
}
return conn;
};
Parallel.ForEach(numbers, localInit, forEachLoop, localFinally);
That being said, most of the time doing concurrent connections to a database is not the right idea, the bottleneck is likely elsewhere and you should use a profiler to see what is really slowing your program down and focus your efforts there.
Sample code for comments:
var numbers = GetDataForNumbers();
List results = new List();
Func> localInit => () => new List();
Func, List> forEachLoop = (number, loopState, localList) => //Begin definition of forLoop
{
using (var conn = new NpgsqlConnection(strConnection))
{
conn.Open();
//This line is going to slow your program down a lot, so i commented it out.
//Console.WriteLine(number.start + " - " + number.end);
using (var cmd = new NpgsqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = String.Format( "SELECT * FROM avl_db.process_near_link({0}, {1});"
, number.start
, number.end);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
//Add a object to the thread local list, we don't need to lock here because we are the only thread with access to it.
localList.Add(reader.GetString(0));
}
}
}
}
return localList;
};
Action> localFinally = localList =>
{
//Combine the local list to the main results, we need to lock here as more than one thread could be merging at once.
lock(results)
{
results.AddRange(localList);
}
};
Parallel.ForEach(numbers, localInit, forEachLoop, localFinally);
//results now contains strings from all the threads here.