使用.NET Framework:3.5 和 Visual Studio 2008
我有一种在不同数据库上执行某些更新的方法。
现在我有一个'foreach循环',在其中调用执行数据库更新的函数。循环根据数据库的数量执行。 客户端服务器中可能有超过700个数据库。因此循环将执行700次,这将花费超过10个小时,这是一个很大的性能问题。
我们遇到的一个解决方案是动态线程创建。
例如:如果我们有100个数据库然后将它分成10个线程,带有1到10个数据库的Method将由thread1处理,接下来10到20个数据库调用将由线程2处理.....就像明智的那样100个数据库使用10个线程更新。
任何人都可以帮助我完成这项工作。如果您有任何其他合适的想法,请分享...
答案 0 :(得分:0)
您可以使用工作线程池,如
public void DoWork()
{
// queue in a loop
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(YourDatabaseWork));
}
private void YourDatabaseWork(Object state)
{
// Insert code to perform a long task.
}
通过这种方式,您可以对您想要执行的每项工作进行排队(假设您不需要太多内存就可以一次完成所有工作)。有一些工作线程可用,所有其他线程将被放入队列中。因此,您应该能够立即“启动”所有线程,并且每次完成一个现有工作线程时,都会处理新的排队项目。
您可以在这里阅读更多内容: http://msdn.microsoft.com/en-us/library/h4732ks0.aspx
如果需要,如何使用输入参数,您可以在这里阅读: http://msdn.microsoft.com/en-us/library/4yd16hza.aspx
答案 1 :(得分:0)
您的问题最好通过异步解决。如果您的更新工作是IO绑定(通常是数据库更新命令),那么您的700个线程将只是坐在那里等待数据库更新在大多数时间内完成。解决方案是异步执行这些更新,然后线程池将拥有足够多的线程。
您可以同时启动所有更新,然后等待任务完成。如果您的更新更复杂并且涉及执行多个查询,请使每个查询异步执行并await
结果。这是一个使用.net 4.5的简单示例:
public async Task UpdateDatabses(List<string> databses)
{
List<Task> updateTasks = new List<Task>();
foreach (var db in databses)
{
updateTasks.Add(UpdateDatabase(db));
}
// asynchronously wait for all the tasks to complete
await Task.WhenAll(updateTasks);
}
public async Task UpdateDatabase(string databse)
{
await /* Update the database */
}
<强>更新强>
对于.NET 3.5,您需要从Nuget安装 Task Parallel Librbary for .NET 3.5 包。我们需要Task.WhenAll
或Task.ConitnueWhenAll
扩展方法,但我无法找到.NET 3.5的任何版本。所以我自己写了一个:
public static class Extensions
{
/// <summary>
/// Returns a task that completes when all the passed tasks are completed
/// </summary>
public static Task WhenAll(IEnumerable<Task> tasks)
{
var tcs = new TaskCompletionSource<object>();
var remainingTasks = tasks.ToList();
int count = remainingTasks.Count();
var exceptions = new List<Exception>();
foreach (var task in remainingTasks)
{
task.ContinueWith(t =>
{
if (Interlocked.Decrement(ref count) == 0)
{
foreach (var task1 in remainingTasks)
{
if (task1.IsFaulted)
{
exceptions.Add(task1.Exception);
}
}
if (exceptions.Any())
{
tcs.SetException(new AggregateException(exceptions));
}
else
{
tcs.SetResult(null);
}
}
});
}
return tcs.Task;
}
}
然后您应该能够将代码更改为以下内容:
public Task UpdateDatabses(List<string> databses)
{
List<Task> updateTasks = new List<Task>();
foreach (var db in databses)
{
updateTasks.Add(UpdateDatabase(db));
}
return Extensions.WhenAll(updateTasks);
}
public Task UpdateDatabase(string databse)
{
return null; /* Update the database using a Task returninng asynchronous operation*/
}