我正在尝试找到一种最佳的并行运行同步C#方法的方法。为此,我在foreach循环中选择了Task.Run()
。即,将所有同步方法添加到任务中,并使用Task.WhenAll(tasks).Wait()
并行执行所有任务。
对不起,如果我使用Task
却没有实际用途。我这样做是因为DBContext
不是线程安全的,并且我有Mandatory
每个事务/数据库记录使用单个DBContext。因此,我认为使方法async
无效,因为我在一种方法中执行的所有任务都是相互依赖的。因此,我认为它可以更好地同时运行相同任务的列表。
注意:我运行了该程序,可以看到Tasks并行运行而没有任何问题,并且创建的记录不是连续的。因此,它证实了这些任务可以并行进行。
请帮助我建议我的实施方案是否可以长期运行。
代码
public void MainMethod()
{
foreach (var x in _ListUser)
tasks.Add(Task.Run(() => Update1Record(x)));
Task.WhenAll(tasks).Wait();
}
public string Update1Record(UserViewModel objUser)
{
using (var VibrantDbContext = new VIBRANT())
using (var AuditDb = new VibrantAuditEntities())
using (var VibrantTransaction = VibrantDbContext.Database.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
using (var AuditTransaction = AuditDb.Database.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
try
{
VibrantDbContext.Database.Initialize(force: false);
AuditDb.Database.Initialize(force: false);
VibrantDbContext.Configuration.AutoDetectChangesEnabled = false;
var _ObjUserItem = FillupDateTimeValues(objUser);
ImportToDB(_ObjUserItem, 0, VibrantDbContext, AuditDb);
BuildImportLog(objUser, VibrantDbContext, AuditDb);
VibrantDbContext.SaveChanges();
AuditDb.SaveChanges();
VibrantTransaction.Commit();
AuditTransaction.Commit();
}
catch (Exception ex)
{
VibrantTransaction.Rollback();
AuditTransaction.Rollback();
throw;
}
}
return "S";
}
答案 0 :(得分:0)
与代码设计相关的观点的结合,何时发生:
foreach (var x in _ListUser)
tasks.Add(Task.Run(() => Update1Record(x)));
Task.WhenAll(tasks).Wait();
_ListUser
拥有1000多个记录,您创建了1000多个Task,无论服务器配置如何,它都会使您的系统瘫痪有哪些选择:
Parallel.Foreach
相对更好,因为它不允许配置太多线程,但对于数据库处理/ IO调用仍然不是一个好主意。Async - Await
,但是挑战在于您的代码是您正在通过同步方法创建任务包装器,这对于Async Await没有帮助,因为它仍然需要后端的后台线程服务器以及类似的问题,只有UI或调用线程将保持响应状态,但是在Async - Await
的情况下,我们需要使用真正的Async API来获得最大的收益。以下是建议的修改:
public string Update1Record
异步,从而返回Task<string>
,我假设DBContext公开了异步API。如下更改MainMethod
:
public async Task MainMethod()
{
foreach (var x in _ListUser)
{
var localx = x;
tasks.Add(Update1Record(localx));
}
await Task.WhenAll(tasks);
}
请注意
localx
要捕获局部变量,这是为了避免关闭问题。
此外,为什么异步在这种情况下会更好:
与您的代码相比,异步处理在后台调度要处理的代码,它使用基于硬件的并发性,从而释放软件线程并允许它们处理更多请求,从而提高了系统可伸缩性。返回时,可以使用任何线程来处理结果。
想法不应阻塞和保留像Thread这样的珍贵资源,每个进程都受其限制。调度和接收结果只是整个处理的一小部分,块线程导致浪费重要的计算资源
答案 1 :(得分:-1)
在这种情况下,可以使用PARALLEL foreach。您可以查看此帖子以获取更多信息: