C#学习教程:我可以使用Parallel.For和sql命令吗?分享


我可以使用Parallel.For和sql命令吗?

我有一类范围

public class avl_range { public long start { get; set; } public long end { get; set; } } 

如果我使用正常的FOR工作完美,但必须等待每个命令完成,每个查询需要8秒,所以10个查询需要80秒。

在Parallel版本中如果我只打印范围工作完美,但如果尝试执行命令说已经在进行中。

{“一项操作已在进行中。”}

我怎么解决这个问题?

 var numbers = new List(); using (var conn = new NpgsqlConnection(strConnection)) { conn.Open(); Action forEachLoop = number => //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)); } } } }; Parallel.ForEach(numbers, forEachLoop); } ); 

仅供参考:我试图解决这个问题,我之前发布过

不能同时使用Npgsql连接 – 在任何给定的时间点只能运行一个命令(换句话说,没有MARS支持)。

打开多个连接以并行执行查询肯定是有意义的。 尽管建立新的物理连接非常昂贵,但连接池非常轻量级,因此重用物理连接的开销非常小。 不这样做的主要原因是,如果您需要多个操作在同一个事务中。

即使您可以使用MARS,连接对象几乎从不是线程安全的,您需要为每个线程建立连接。 Parallel.ForEach有重载使得这很容易 ,它具有在线程开始和结束时运行的函数。

 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); 

话虽这么说,大部分时间与数据库并发连接都不是正确的想法,瓶颈可能在其他地方,你应该使用分析器来查看什么真正减慢你的程序,并集中你的努力。


评论示例代码:

上述就是C#学习教程:我可以使用Parallel.For和sql命令吗?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

 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. 

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/1031589.html

发表评论

邮箱地址不会被公开。 必填项已用*标注