• 全部
  • C#综合技术
  • C#互联网桌面应用
  • AppLauncher
  • WinForm&WPF
  • C#开发新技术
  • 问答

C#双重for循环中嵌套foreach速度太慢,有什么方法可以改进的

nzzb1985 2010-05-26 11:05:18
我在项目中将接收到的数据包全放入数据包类DataModel集合list中,其中 Tnum 是线程编号,Pnum 是包编号,我需要将数据包按照顺序依次写入MyFileStream 中。
接收到数据包的速度很快,但是用的双重for循环后再嵌套foreach向MyFileStream 写入的速度太慢,有什么方法可以改进的??

for (int i = 0; i < 4; i++)
{
for (int j = 0; j < list.Count; j++)
{
foreach (DataModel dm in list)
{
if (dm.Tnum == i)
{
if (dm.Pnum == j)
{
MyFileStream.Write(dm.Data, 0, dm.Data.Length);
list.Remove(dm);
break;
}

}
}
}
}
...全文
707 点赞 收藏 9
写回复
9 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
nzzb1985 2010-05-26
[Quote=引用 7 楼 longlongagoimboy 的回复:]
LZ,我想你可能还需要确定一下是检索数据慢还是写入文件慢。
如果是写入文件花的时间比较多(可以用一个静态的数据list来模拟),那么可以采用wuyazhe的方法。
如果是检索慢(可能由于线程同步、数据同步保护等原因造成的等待),那么需要找到慢的地方。
[/Quote]

我试了一下,应该是写入慢。采用了wuyazhe的方法,速度稍微快了点,但现在主要就是丢数据,1个是传输的方面,1个就是在接收到后循环遍历的时候。
传输的时候,一样的程序,有的时候能接到全部的数据包8112个,但有的时候却接不全,甚至只能接1半。
循环的时候,8112个包,却只能找到7097个包,剩下的包就不知道为什么会找不到了。。。
郁闷了···········
回复
md5e 2010-05-26
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < list.Count; j++)
{
if(list[j].Tnum==1 && list[j].Pnum==j)
{
bytes.AddRange(dm.Data);
list.Remove(dm);
}
}
}
回复
Jimmy_Xia 2010-05-26
LZ,我想你可能还需要确定一下是检索数据慢还是写入文件慢。
如果是写入文件花的时间比较多(可以用一个静态的数据list来模拟),那么可以采用wuyazhe的方法。
如果是检索慢(可能由于线程同步、数据同步保护等原因造成的等待),那么需要找到慢的地方。
回复
skep99 2010-05-26
[Quote=引用 4 楼 nzzb1985 的回复:]
引用 2 楼 skep99 的回复:
能序列化的话,直接序列化你的DataModel list


序列化?怎么序列化DataModel list?
我这是按照你的思路把线程编号和包编号都放到数据包里面发送过去了,收到的数据包的个数是正确的,但就是组合的时候会丢数据。不知道是什么原因,在写入的代码设断点调试的时候,因为循环的太多次了,速度慢不说,调试的时候也不好调试,要循环n千次。。
[/Quote]

两个话题,既然这么传了,就先说这么处理的办法吧

总共要传送多少个包知道吧?
接收就不要用list了,直接声明一个数组arr,大小是[包的数量]

过来一个DataModel 得到dm.Tnum,Tnum对应arr的下标[Tnum],
即arr[dm.Tnum]=dm;
这样得到的arr数组是正序排列的
回复
兔子党-顾问 2010-05-26
我的意思,你可以等效的使用优化后的代码如下:
List<byte> bytes = new List<byte>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < list.Count; j++)
{
foreach (DataModel dm in list)
{
if (dm.Tnum == i && dm.Pnum == j)
{
bytes.AddRange(dm.Data);
list.Remove(dm);
break;
}
}
}
}

MyFileStream.Write(bytes.ToArray(),0,bytes.Count);
回复
nzzb1985 2010-05-26
[Quote=引用 2 楼 skep99 的回复:]
能序列化的话,直接序列化你的DataModel list
[/Quote]

序列化?怎么序列化DataModel list?
我这是按照你的思路把线程编号和包编号都放到数据包里面发送过去了,收到的数据包的个数是正确的,但就是组合的时候会丢数据。不知道是什么原因,在写入的代码设断点调试的时候,因为循环的太多次了,速度慢不说,调试的时候也不好调试,要循环n千次。。
回复
nzzb1985 2010-05-26
[Quote=引用 1 楼 wuyazhe 的回复:]
减少io操作次数,拼接发送数组后统一发就会快。
[/Quote]

你说的意思是不是找到1个数据包就向里面写1次?
那找到的数据包放到哪?
回复
skep99 2010-05-26
能序列化的话,直接序列化你的DataModel list
回复
兔子党-顾问 2010-05-26
减少io操作次数,拼接发送数组后统一发就会快。
回复
相关推荐
综教楼后的那个坑用双向链表实现 描述   在 LIT 综教楼后有一个深坑,关于这个坑的来历,有很多种不同的说法。其中一种说法是,在很多年以前,这个坑就已经在那里了。这种说法也被大多数人认可,这是因为该坑有一种特别的结构,想要人工建造是有相当困难的。   从横截面图来看,坑底成阶梯状,由从左至右的 1..N 个的平面构成(其中 1 ≤ N ≤ 100,000),如图:    *            * :    *            * :    *            * 8    *    **      * 7    *    **      * 6    *    **      * 5    *    ********* 4 <- 高度    *    ********* 3    ************** 2    ************** 1 平面 |  1  |2|   3    | 每个平面 i 可以用两个数字来描述,即它的宽度 Wi 和高度 Hi,其中 1 ≤ Wi ≤ 1,000、1 ≤ Hi ≤ 1,000,000,而这个坑最特别的地方在于坑底每个平面的高度都是不同的。每到夏天,雨水会把坑填满,而在其它的季节,则需要通过人工灌水的方式把坑填满。灌水点设在坑底位置最低的那个平面,每分钟灌水量为一个单位(即高度和宽度均为 1)。随着水位的增长,水自然会向其它平面扩散,当水将某平面覆盖且水高达到一个单位时,就认为该平面被水覆盖了。   请你计算每个平面被水覆盖的时间。    灌水 水满后自动扩散 | | * | * * | * * * * V * * V * * * * * * .... * *~~~~~~~~~~~~* * ** * *~~~~** : * *~~~~**~~~~~~* * ** * *~~~~** : * *~~~~**~~~~~~* * ** * *~~~~**~~~~~~* *~~~~**~~~~~~* * ********* *~~~~********* *~~~~********* *~~~~********* *~~~~********* *~~~~********* ************** ************** ************** ************** ************** **************    4 分钟后    26 分钟后        50 分钟后    平面 1 被水覆盖     平面 3 被水覆盖    平面 2 被水覆盖输入   输入的第一行是一个整数 N,表示平面的数量。从第二行开始的 N 行上分别有两个整数,分别表示平面的宽度和高度。 输出   输出每个平面被水覆盖的时间。
发帖
C#
创建于2007-09-28

10.5w+

社区成员

.NET技术 C#
申请成为版主
帖子事件
创建了帖子
2010-05-26 11:05
社区公告

让您成为最强悍的C#开发者