循环执行时间太长(一年循环365天)
本文关键字:循环 一年 365天 执行时间 | 更新日期: 2023-09-27 18:14:15
我有一个人力列表(40人)。我需要为每个人循环一年(365天)来提取每天的数据。但这太花时间了。有什么提高速度的建议或不同的方法吗?
for (int man=0;man<40;man++)
{
for (DateTime date = DateTime.Now.Date;date<DateTime.Now.AddYears(1);date=date.AddDays(1))
{
//do stuff
}
}
编辑:东西包括从数据库中提取数据,我得到每个人参与的项目,以及每个人项目的开始和结束日期。(每个人都有自己的桌子,还有一张主桌子,上面列着所有人的名单)。我有一个数据视图,我在纵轴上显示了40个人。横轴365天。取决于号码。项目,每个人都参与,我需要彩色编码相应的细胞。
编辑2://A是一个连接到数据库,转发查询并返回结果的类
void colourchanger()
{
for (int m = 0; m < i; m++)//i=40
{
int copy = m;
List<string>[] list = new List<string>[5];
int number = A.Countproj(abc);//return no. of projects under man
list = A.manprojselect(abc);//returns project details
thread[copy] = new Thread(() => threader(copy,2*copy,list,number));
thread[copy].Start();
}
}
void threader(int p, int x,List<string>[] list,int numberer)
{
DateTime labeldate;
DataGridViewCellStyle AL = new DataGridViewCellStyle();
AL.BackColor = Color.Brown;//AL
DataGridViewCellStyle NS = new DataGridViewCellStyle();
NS.BackColor = Color.Aqua;//NS
DataGridViewCellStyle training = new DataGridViewCellStyle();
training.BackColor = Color.Maroon;//training
DataGridViewCellStyle one = new DataGridViewCellStyle();
one.BackColor = Color.Green;//one project
DataGridViewCellStyle overseas = new DataGridViewCellStyle();
overseas.BackColor = Color.Blue;//overseas
DataGridViewCellStyle two = new DataGridViewCellStyle();
two.BackColor = Color.Yellow;//2 projects
DataGridViewCellStyle three = new DataGridViewCellStyle();
three.BackColor = Color.Red;//3 projects
DataGridViewCellStyle unfeasible = new DataGridViewCellStyle();
unfeasible.BackColor = Color.Black;//self explanatory
DataGridViewCellStyle none = new DataGridViewCellStyle();
none.BackColor = Color.Gray;//self explanatory
string[] projname;
string[] country;
string[] start;
string[] end;
string temp;
DateTime startdate;
DateTime enddate;
int[] track = new int[366];
string[] projnames = new string[366];
for (int y = 0; y < 366; y++)
{
projname = list[0].ToArray();
country = list[2].ToArray();
start = list[3].ToArray();
end = list[4].ToArray();
temp = dataGridView1.Rows[x].Cells[y].ToolTipText;
temp = temp[0].ToString() + temp[1].ToString() + temp[2].ToString() + temp[3].ToString() + temp[4].ToString() + temp[5].ToString() + temp[6].ToString() + temp[7].ToString() + temp[8].ToString() + temp[9].ToString();
labeldate = DateTime.ParseExact(temp,
"dd-MM-yyyy",
CultureInfo.InvariantCulture);
for (int l = 0; l < numberer; l++)
{
startdate = DateTime.ParseExact(start[l],
"dd-MM-yyyy HH:mm:ss",
CultureInfo.InvariantCulture);
enddate = DateTime.ParseExact(end[l],
"dd-MM-yyyy HH:mm:ss",
CultureInfo.InvariantCulture);
int r1 = DateTime.Compare(startdate, labeldate);
int r2 = DateTime.Compare(labeldate, enddate);
if (r1 <= 0 && r2 <= 0)
{
track[y]++;
projnames[y] = projnames[y] + ", " + projname[l];
if (String.Compare(country[l], "Singapore ") != 0)
{
track[y] = 10;
projnames[y] = " " + projname[l];
}
if (String.Compare(projname[l], "ANNUAL LEAVE") == 0)
{
track[y] = 20;
projnames[y] = " " + projname[l];
}
if (String.Compare(projname[l], "NATIONAL SERVICE") == 0)
{
track[y] = 30;
projnames[y] = " " + projname[l];
}
if (String.Compare(projname[l], "TRAINING") == 0)
{
track[y] = 40;
projnames[y] = " " + projname[l];
}
}
}
}
for (int y = 0; y < 366; y++)
{
if (track[y] == 0)
{
dataGridView1.Rows[x].Cells[y].Style = none;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 1)
{
dataGridView1.Rows[x].Cells[y].Style = one;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 2)
{
dataGridView1.Rows[x].Cells[y].Style = two;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 3)
{
dataGridView1.Rows[x].Cells[y].Style = three;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 10)
{
dataGridView1.Rows[x].Cells[y].Style = overseas;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 20)
{
dataGridView1.Rows[x].Cells[y].Style = AL;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 30)
{
dataGridView1.Rows[x].Cells[y].Style = NS;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 40)
{
dataGridView1.Rows[x].Cells[y].Style = training;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] > 3 && (track[y] != 10 && track[y] != 20 && track[y] != 30 && track[y] != 40))
{
dataGridView1.Rows[x].Cells[y].Style = unfeasible;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
}
}
SQL CE
编辑3:Manprojselect()张贴
public List<string>[] manprojselect(string manpowername)
{
string query = "SELECT * FROM "+ manpowername;
//Create a list to store the result
List<string>[] list = new List<string>[5];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
list[3] = new List<string>();
list[4] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
SqlCeCommand cmd = new SqlCeCommand(query, connection);
//Create a data reader and Execute the command
SqlCeDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["Name"] + "");
list[1].Add((dataReader["Allotment_number"]).ToString() + "");
list[2].Add(dataReader["Country"] + "");
list[3].Add(dataReader["Start_date"] + "");
list[4].Add(dataReader["End_date"] + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
else
{
return list;
}
}
它只循环365*40次,这是一个简单的检查。以上所有的减速都是由//do stuff
引起的。
我想补充的是,这实际上是一个常见的问题——到达//do stuff
所需的时间长度乘以365*40(假设东西在人和天上花费的时间是一致的)。
尝试从数据库中提取数据作为单个批量查询或至少每个人单个查询。
用代码分析数据,即使使用未优化的代码,它也会比查询每个单元格快得多。
如前所述,//do stuff
是罪魁祸首。
在没有更多信息的情况下,我只能建议您尝试使用Parallel.For
方法并使用更多线程(如果您有多个可用的逻辑CPU内核,则很有用)。
请记住,这将要求您考虑lock
,因为并发访问共享变量可能会导致问题。
只是为了好玩。我该如何优化这个循环?我已经试过了
void Main()
{
Stopwatch sw = new Stopwatch();
sw.Start();
int max = DateTime.Today.AddYears(1).Subtract(DateTime.Today).Days;
for (int man=0;man<40;man++)
{
for (int x = 0; x <= max; x++)
{
//do stuff
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
sw.Reset();
sw.Start();
for (int man=0;man<40;man++)
{
for (DateTime date = DateTime.Now.Date;date<DateTime.Now.AddYears(1);date=date.AddDays(1))
{
//do stuff
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
}
第一个循环以天为单位计算一年的长度,然后循环一个整数,第二个是op。
第一个循环的速度快了19毫秒。好了,玩够了,继续工作,试着优化做的事情
您的问题是您试图对数据库进行365*40个单独的查询。通常,您希望在服务器端评估更多此类内容。
回答你的直接问题:是的,你可以使代码运行得更快。然而,这并不能解决你的问题。
您可以将当前日期存储到一个局部变量中,然后使用它而不是对DateTime进行所有这些调用。现在,它将每次检查系统时间。
var now=DateTime.Now;
var yearFromNow = DateTime.Now.AddYears(1);
…然后在循环中使用这些新变量。
您还可以将所有日期存储在列表中,从而减少循环内所需的计算次数:
var dates = Enumerable.Range(0,365).Select(n=>now.AddDays(n)).ToList();
然后你可以在循环中访问这个列表:
for (int man=0;man<40;man++)
{
foreach (var dt in dates)
{
//do stuff
}
}
…但这并不是您的主要性能问题所在。相反,您应该在这里发布//do stuff主体,以及您正在使用的数据库访问类型(LINQ2Sql,EF等),以便我们可以看到整个事情是否可以优化显著增益。
不应该每次循环都重新打开连接。