使用相同的事务实例一个接一个地等待所有任务失败 c#
Wait all tasks one by one with the same transaction instance failed c#
我在一个事务实例中使用一个接一个的等待方法,在调用事务实例的 Commit 方法时出现此错误:
我在这里错过了什么?
这是代码:
.
.
.
using Dapper;
using DapperExtensions;
.
.
.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
var tlis = GetTlis(connection).ToList();
using (var trans = connection.BeginTransaction())
{
var tasks = tlis.Take(10).Select(tli => Task.Factory.StartNew(
(dynamic @params) =>
{
ProcessTli(@params.Connection, @params.Transaction, tli);
},
new { Connection = connection, Transaction = trans }
)).ToList();
var tlisAmount = 0;
while (tasks.Count > 0)
{
//const int timeout = 3600*1000;
var winner = Task.WaitAny(tasks.ToArray());
if (winner < 0)
break;
tlisAmount++;
tasks.RemoveAt(winner);
Cmd.Write("({0}%) ", tlisAmount*100/tlis.Count);
var timeSpan = TimeSpan.FromSeconds(Convert.ToInt32(stopWatch.Elapsed.TotalSeconds));
Cmd.Write(timeSpan.ToString("c") + " ");
Cmd.Write("Processing {0} of {1} ", tlisAmount, tlis.Count);
Cmd.Write('\r');
}
try
{
trans.Commit();
}
catch (Exception e)
{
Cmd.WriteLine(e.Message);
trans.Rollback();
}
finally
{
connection.Close();
}
}
}
private static void ProcessTli(IDbConnection connection, IDbTransaction transaction, Tli tli)
{
var quotesTask = Task.Factory.StartNew(() => GetQuotesByTli(connection, transaction, tli));
quotesTask.ContinueWith(quotes =>
{
quotes.Result.ToList().ForEach(quote =>
{
var tliTransaction = new TliTransaction(quote);
connection.Insert(tliTransaction, transaction);
});
});
var billOfLadingsTask = Task.Factory.StartNew(() =>GetBillOfLadings(connection, transaction, tli));
billOfLadingsTask.ContinueWith(billOfLadings =>
{
var bolGroupsByDate = from bol in billOfLadings.Result.ToList()
group bol by bol.Year;
bolGroupsByDate.ToList().ForEach(bolGroupByDate =>
{
var bol = new BillOfLading
{
As400FormatQuoteDate = bolGroupByDate.ElementAt(0).As400FormatQuoteDate,
CommodityCode = tli.CommodityCode,
TariffOcurrenciesAmount = bolGroupByDate.Count(),
TliNumber = tli.TliNumber
};
var tliTransaction = new TliTransaction(tli, bol);
connection.Insert(tliTransaction, transaction);
});
});
Task.WaitAll(quotesTask, billOfLadingsTask);
}
提前致谢
我会做这样的事情(注意这显示了过程,而不是确切的代码...)
public void ModifyData()
{
using (var connection = new SqlConnection(connectionString))
{
var tlis = GetTlis(connection).ToList();
connection.Open();
Quotes quotes;
BillOfLading billOfLading;
using (var trans = connection.BeginTransaction())
{
quotes = GetQuotesByTli(connection, transaction, tli);
billOfLading = GetBillOfLadings(connection, transaction, tli);
}
}
// Process those items retrieved from the database.
var processedItems = this.Process(/* the items that you want to process */);
using (var connection = new SqlConnection(connectionString))
{
var tlis = GetTlis(connection).ToList();
connection.Open();
using (var trans = connection.BeginTransaction())
{
// do all your inserts.
}
}
}
那么你会运行它:
await Task.Run(() => ModifyData());
这个 resource 展示了一个很好的 运行 多任务示例。
我在一个事务实例中使用一个接一个的等待方法,在调用事务实例的 Commit 方法时出现此错误:
我在这里错过了什么?
这是代码:
.
.
.
using Dapper;
using DapperExtensions;
.
.
.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
var tlis = GetTlis(connection).ToList();
using (var trans = connection.BeginTransaction())
{
var tasks = tlis.Take(10).Select(tli => Task.Factory.StartNew(
(dynamic @params) =>
{
ProcessTli(@params.Connection, @params.Transaction, tli);
},
new { Connection = connection, Transaction = trans }
)).ToList();
var tlisAmount = 0;
while (tasks.Count > 0)
{
//const int timeout = 3600*1000;
var winner = Task.WaitAny(tasks.ToArray());
if (winner < 0)
break;
tlisAmount++;
tasks.RemoveAt(winner);
Cmd.Write("({0}%) ", tlisAmount*100/tlis.Count);
var timeSpan = TimeSpan.FromSeconds(Convert.ToInt32(stopWatch.Elapsed.TotalSeconds));
Cmd.Write(timeSpan.ToString("c") + " ");
Cmd.Write("Processing {0} of {1} ", tlisAmount, tlis.Count);
Cmd.Write('\r');
}
try
{
trans.Commit();
}
catch (Exception e)
{
Cmd.WriteLine(e.Message);
trans.Rollback();
}
finally
{
connection.Close();
}
}
}
private static void ProcessTli(IDbConnection connection, IDbTransaction transaction, Tli tli)
{
var quotesTask = Task.Factory.StartNew(() => GetQuotesByTli(connection, transaction, tli));
quotesTask.ContinueWith(quotes =>
{
quotes.Result.ToList().ForEach(quote =>
{
var tliTransaction = new TliTransaction(quote);
connection.Insert(tliTransaction, transaction);
});
});
var billOfLadingsTask = Task.Factory.StartNew(() =>GetBillOfLadings(connection, transaction, tli));
billOfLadingsTask.ContinueWith(billOfLadings =>
{
var bolGroupsByDate = from bol in billOfLadings.Result.ToList()
group bol by bol.Year;
bolGroupsByDate.ToList().ForEach(bolGroupByDate =>
{
var bol = new BillOfLading
{
As400FormatQuoteDate = bolGroupByDate.ElementAt(0).As400FormatQuoteDate,
CommodityCode = tli.CommodityCode,
TariffOcurrenciesAmount = bolGroupByDate.Count(),
TliNumber = tli.TliNumber
};
var tliTransaction = new TliTransaction(tli, bol);
connection.Insert(tliTransaction, transaction);
});
});
Task.WaitAll(quotesTask, billOfLadingsTask);
}
提前致谢
我会做这样的事情(注意这显示了过程,而不是确切的代码...)
public void ModifyData()
{
using (var connection = new SqlConnection(connectionString))
{
var tlis = GetTlis(connection).ToList();
connection.Open();
Quotes quotes;
BillOfLading billOfLading;
using (var trans = connection.BeginTransaction())
{
quotes = GetQuotesByTli(connection, transaction, tli);
billOfLading = GetBillOfLadings(connection, transaction, tli);
}
}
// Process those items retrieved from the database.
var processedItems = this.Process(/* the items that you want to process */);
using (var connection = new SqlConnection(connectionString))
{
var tlis = GetTlis(connection).ToList();
connection.Open();
using (var trans = connection.BeginTransaction())
{
// do all your inserts.
}
}
}
那么你会运行它:
await Task.Run(() => ModifyData());
这个 resource 展示了一个很好的 运行 多任务示例。