在我的应用程序中,我打开大约70个服务器的连接,每个服务器平均有8个数据库(服务器分为环境,即开发,生产,UaT,坐,培训,misc,Qa)。 应用程序将检查每个数据库中是否存在用户,并在用户存在时获取详细信息。 我使用了一种方法来调用服务,这个方法会将用户id作为输入传递给服务,将检查用户跨数据库并获取详细信息。 整个过程花费了太多时间,UI中的空闲时间约为5-10分钟。
我们如何调整此应用程序的性能。我想在环境基础上实现多线程和获取扣留。但我不确定我们是否可以在应用程序中使用返回类型调用方法并使用输入参数。
请建议一种提高效果的方法。
public List<AccessDetails> GetAccessListOfMirror(string mirrorId,string server)
{
List<AccessDetails> accessOfMirror = new List<AccessDetails>();
string loginUserId = SessionManager.Session.Current.LoggedInUserName;
string userPassword = SessionManager.Session.Current.Password;
using (Service1Client client = new Service1Client())
{
client.Open();
accessOfMirror = client.GetMirrorList(mirrorId, server, loginUserId, userPassword);
}
return accessOfMirror;
}
服务方法
public List<AccessDetails> GetMirrorList(string mirrorId, string server, string userId, string userPassword)
{
string mirrorUser = mirrorId.ToString();
List<ConnectionStringContract> connectionStrings = new List<ConnectionStringContract>();
try
{
connectionStrings = GetConnectionString(server);
}
catch (FaultException<ServiceData> exe)
{
throw exe;
}
AseConnection aseConnection = default(AseConnection);
List<AccessRequest> mirrorUsers = new List<AccessRequest>();
List<FacetsOnlineAccess> foaAccess = new List<FacetsOnlineAccess>();
List<AccessDetails> accessDetails = new List<AccessDetails>();
AccessDetails accDetails = new AccessDetails();
AccessRequest access;
if (!String.IsNullOrEmpty(server))
connectionStrings = connectionStrings.Where(x => x.Server == server).ToList();
foreach (ConnectionStringContract connection in connectionStrings)
{
string connectionString = connection.ConnectionString;
AseCommand aseCommand = new AseCommand();
using (aseConnection = new AseConnection(connectionString))
{
try
{
aseConnection.Open();
try
{
List<Parameter> parameter = new List<Parameter>();
Parameter param;
param = new Parameter();
param.Name = "@name_in_db";
param.Value = mirrorUser.ToLower().Trim();
parameter.Add(param);
int returnCode = 0;
DataSet ds = new DataSet();
try
{
ds = DataAccess.ExecuteStoredProcedure(connectionString, Constant.SP_HELPUSER, parameter, out returnCode);
}
catch (Exception ex)
{
}
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow row in ds.Tables[0].Rows)
{
access = new AccessRequest();
if (row.ItemArray[0].ToString() == mirrorUser)
access.Group = row.ItemArray[2].ToString();
else
access.Group = row.ItemArray[0].ToString();
access.Environment = connection.Environment.Trim();
access.Server = connection.Server.Trim();
access.Database = connection.Database.Trim();
mirrorUsers.Add(access);
}
}
}
catch (Exception ex)
{
}
}
catch (Exception ConEx)
{
}
}
}
accDetails.AccessList = mirrorUsers;
//accDetails.FOAList = foaAccess;
accessDetails.Add(accDetails);
return accessDetails;
}
提前致谢
答案 0 :(得分:1)
循环有时会降低速度,尤其是循环内部的循环。 I / O操作总是很慢。你有一个循环i?o。因此,如果您要在并行线程上执行此I / O操作,性能会提高。
你可以翻译
foreach (ConnectionStringContract connection in connectionStrings)
{
...
}
成:
Parallel.ForEach(connectionStrings, connectionString =>
{
...
}
在内部你应该锁定常用的变量,例如锁定mirrorUsers
。
我认为这是一个很好的开始。同时我会寻找其他性能问题。
答案 1 :(得分:-1)
你应该能够利用多线程而不会有太多麻烦...
您应该使用线程池,因此不会产生太多同时运行的线程。你可以在这里阅读内置的线程池:
http://msdn.microsoft.com/en-us/library/3dasc8as%28v=vs.80%29.aspx
您应该做的是将foreach
循环的主体提取为静态方法。任何参数都应该成为可以传递给线程的模型。因为那时你可以使用ThreadPool.QueueUserWorkItem(object)
来启动线程。
关于写入同一资源(列表或其他)的多个线程,您可以使用任何类型的互斥锁,锁或线程安全组件。使用锁非常简单:
http://msdn.microsoft.com/en-us/library/c5kehkcz%28v=vs.80%29.aspx