动态线程如何帮助解决我的性能问题

本文关键字:解决 我的 性能 问题 帮助 线程 何帮助 动态 | 更新日期: 2023-09-27 18:13:32

。使用的.NET Framework:3.5Visual Studio 2008

我有一个在不同数据库上执行某些更新的方法。

现在我有一个"foreach循环",其中调用了用于执行数据库更新的函数。循环根据数据库的数量执行。客户端服务器中可能有700多个数据库。因此,循环将执行700次,这需要超过10个小时,这是一个很大的性能问题。

我们遇到的一个解决方案是动态线程创建。

例如:如果我们有100个数据库,然后将其拆分为10个线程,具有1到10个数据库的方法将由线程1处理,接下来10到20个数据库调用将由线程2处理……就像使用10个线程更新的100个数据库一样。

有谁能帮我解决这个问题吗。如果你还有其他合适的想法,请分享。。。

动态线程如何帮助解决我的性能问题

您可以使用类似的工作线程池

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

您的问题最好通过异步来解决。如果你的更新工作是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,您需要为安装任务并行Librbary。NET 3.5包。我们需要Task.WhenAllTask.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*/
    }