我有一份人力清单(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
}
}
编辑:东西涉及从数据库中提取数据,我获得每个人参与的项目,以及每个人的项目的开始和结束日期。 (每个人都有自己的桌子,并且有一张主人桌,上面列出了所有人的名单)。我有一个datagridview,其中我在垂直轴上显示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];
}
}
}
使用的DB: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;
}
}
答案 0 :(得分:4)
它只循环365 * 40次,这是一个简单的检查。除此之外的所有减速都是由//do stuff
引起的。
我补充一点,这实际上是一个常见的问题 - 然后//do stuff
所花费的时间长度乘以365 * 40(假设东西在人和天上花费的时间相同)。
答案 1 :(得分:3)
尝试从数据库中提取数据作为单个批量查询或至少每个人的单个查询。
在代码中分析您的数据,即使使用未经优化的代码,它也会比查询每个单元格的速度快得多。
答案 2 :(得分:2)
如前所述,//do stuff
是罪魁祸首。
如果没有更多信息,我只建议您尝试使用Parallel.For
方法并使用更多线程(如果您有多个逻辑CPU核心,则非常有用)。
请记住,这需要您考虑lock
,因为对共享变量的并发访问可能会导致问题。
答案 3 :(得分:1)
只是为了好玩。我怎么能优化那个循环?我试过这个
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毫秒。
好吧,足够有趣,重新开始工作并尝试优化做事
答案 4 :(得分:0)
您的问题是您尝试对数据库执行365 * 40个单独的查询。通常,您希望在服务器端评估更多此项。
回答您的直接问题:是的,您可以让代码更快。但是,这不会解决您的问题。
您可以将当前日期存储到本地变量,然后使用它而不是对DateTime.Now执行所有这些调用,这将每次检查系统时间。
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等),这样我们就能看出整个事情是否可以针对显着的收益。
不应为每个循环传递重新打开连接。