C# 循环读写数据中途突然变慢

我写了个转换数据的小程序,前面500多个数据都能正常速度(大概25个/分钟)读写,但之后速度突然变慢(6-7个/分钟)。哪里出现了问题?另我用另一个程序读写就没出现这个问题。
注:数据大小相同,读写都在移动硬盘

private void bt_convert_Click(object sender, EventArgs e)
        {
            char[] Textheader = new char[3200];
            string dir = comboBox1.Text;
            for (int i = 0; i < listBox_segd.Items.Count; i++)
            {
                var segdHD = ReadSegd(listBox_segd.Items[i].ToString());
                var segdhd2segyhd = SegdHeader2SegyHeader(segdHD.Item1, segdHD.Item2);
                WriteSegy(listBox_segd.Items[i].ToString(), dir, Textheader, segdhd2segyhd.Item1,
                    segdhd2segyhd.Item2, segdhd2segyhd.Item3, segdhd2segyhd.Item4, segdhd2segyhd.Item5, segdhd2segyhd.Item6, segdHD.Item3);

                segdHD = null;
                segdhd2segyhd = null;
            }
        }

private Tuple, List>, List> ReadSegd(string segdfile)
        {
            List gh = new List();
            List> th = new List>();
            List traces = new List();
            try
            {
                using (FileStream fs = new FileStream(segdfile, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryReader br = new BinaryReader(fs))
                    {
                        ////////////////////////1个总头块///////////////////////////////////////////////
                        byte[] Gh0 = br.ReadBytes(32);
                        if (Gh0[0].ToString("x") + Gh0[1].ToString("x") == "ffff")
                        { gh.Add("ffff"); }
                        else
                        { gh.Add(int.Parse(Gh0[0].ToString("x") + Gh0[1].ToString("x"))); } 
                        gh.Add(int.Parse(Gh0[2].ToString("x") + Gh0[3].ToString("x")));     
                        gh.Add(int.Parse(Gh0[11].ToString("x").Substring(0, 1)));            
                        gh.Add(float.Parse(Gh0[22].ToString()) / 16);                           
                        string nn = ((Gh0[25].ToString("x") + Gh0[26].ToString("x")).Substring(1, 3));
                        if (nn == "fff")
                        { gh.Add(nn); }
                        else
                        { gh.Add(int.Parse(nn) * 1.024); }                          

                        gh.Add(int.Parse(Gh0[27].ToString("x")));                
                        gh.Add(int.Parse(Gh0[28].ToString("x")));                

                        nn = Gh0[30].ToString("x");
                        if (nn == "ff")
                        { gh.Add(nn); }
                        else
                        { gh.Add(int.Parse(nn)); }                                

                        nn = Gh0[31].ToString("x");
                        if (nn == "ff")
                        { gh.Add(nn); }
                        else
                        { gh.Add(int.Parse(nn)); }                                
                        ////////////////////////1个总头块/////////////////////////////////////////////
                        ///
                        ////////////////////////2个总头块//////////////////////////////////////////////
                        byte[] Gh1 = br.ReadBytes(32);
                        gh.Add(Convert.ToInt32(Convert.ToString(Gh1[0], 2).PadLeft(8, '0') +
                            Convert.ToString(Gh1[1], 2).PadLeft(8, '0') + Convert.ToString(Gh1[2], 2).PadLeft(8, '0'), 2));  
                        gh.Add(Convert.ToInt32(Convert.ToString(Gh1[3], 2).PadLeft(8, '0') + Convert.ToString(Gh1[4], 2).PadLeft(8, '0'), 2));     
                        gh.Add(Convert.ToInt32(Convert.ToString(Gh1[5], 2).PadLeft(8, '0') + Convert.ToString(Gh1[6], 2).PadLeft(8, '0'), 2));     
                        gh.Add(Convert.ToInt32(Convert.ToString(Gh1[7], 2).PadLeft(8, '0') + Convert.ToString(Gh1[8], 2).PadLeft(8, '0'), 2));     
                        gh.Add((Convert.ToInt32(Convert.ToString(Gh1[10], 2).PadLeft(8, '0'), 2) * 10.0 + Convert.ToInt32(Convert.ToString(Gh1[11], 2).PadLeft(8, '0'), 2)) / 10.0); 
                        gh.Add(Convert.ToInt32(Convert.ToString(Gh1[12], 2).PadLeft(8, '0') + Convert.ToString(Gh1[13], 2).PadLeft(8, '0'), 2));     
                        gh.Add(Convert.ToInt32(Convert.ToString(Gh1[14], 2).PadLeft(8, '0') +
                            Convert.ToString(Gh1[15], 2).PadLeft(8, '0') + Convert.ToString(Gh1[16], 2).PadLeft(8, '0'), 2)); 
                        ////////////////////////2个总头块//////////////////////////////////////////////
                        ///
                        ////////////////////////第N个总头块//////////////////////////////////////////////
                        if (gh[2] > 1)
                        {
                            byte[] GhN = br.ReadBytes(32 * (gh[2] - 1));
                            gh.Add(Convert.ToInt32(Convert.ToString(GhN[3], 2).PadLeft(8, '0') +
                            Convert.ToString(GhN[4], 2).PadLeft(8, '0') + Convert.ToString(GhN[5], 2).PadLeft(8, '0'), 2)); 
                            gh.Add(Convert.ToInt32(Convert.ToString(GhN[8], 2).PadLeft(8, '0') +
                            Convert.ToString(GhN[9], 2).PadLeft(8, '0') + Convert.ToString(GhN[10], 2).PadLeft(8, '0'), 2)); 
                        }
                        ////////////////////////第N个总头块//////////////////////////////////////////////
                        ///
                        ////////////////////////扫描头块//////////////////////////////////////////////
                        if (gh[6] > 1)
                        {
                            byte[] Sch = br.ReadBytes(32 * gh[6]);
                            gh.Add(int.Parse(Sch[8].ToString("x") + Sch[9].ToString("x")));            
                            gh.Add(int.Parse(Sch[10].ToString("x")) / 10);                               
                            gh.Add(int.Parse(Sch[40].ToString("x") + Sch[41].ToString("x")));          
                            gh.Add(int.Parse(Sch[42].ToString("x")) / 10);                               
                        }
                        ////////////////////////扫描头块//////////////////////////////////////////////
                        ///
                        ////////////////////////扩展头块和外部头块//////////////////////////////////////////////
                        if (gh[7] > 0)
                        { br.ReadBytes(32 * gh[7]); }
                        if (gh[8] > 0)
                        { br.ReadBytes(32 * gh[7]); }
                        ////////////////////////扩展头块和外部头块//////////////////////////////////////////////
                        ///
                        //////////////////////////////道头和扩展道头//////////////////////////////////////////                                  
                        byte[] Th = br.ReadBytes(20);
                        gh.Add(Convert.ToInt32(Convert.ToString(Th[9], 2).PadLeft(8, '0'), 2));     
                        byte[] Th1 = br.ReadBytes(20);
                        gh.Add(Convert.ToInt32(Convert.ToString(Th1[7], 2).PadLeft(8, '0') +
                            Convert.ToString(Th1[8], 2).PadLeft(8, '0') + Convert.ToString(Th1[9], 2).PadLeft(8, '0'), 2)); 
                        //////////////////////////////道头和扩展道头//////////////////////////////////////////
                        ///

                        int trchd_bytes = 20 + gh[22] * 32;                              
                        FileInfo finfo = new FileInfo(segdfile);                                      
                        long size = (gh[2] + 1) * 32 + gh[6] * 32 + (gh[7] + gh[8]) * 32 +
                            (trchd_bytes + gh[23] * 4) * (gh[18] + gh[20]) + gh[14] * 32; 
                        if (finfo.Length != size)                                                        
                        { MessageBox.Show("Read Segd file ERRO", "ERRO", MessageBoxButtons.OK); return null; }

                        if (gh[19] == 9)                                                               
                            fs.Seek((gh[2] + 1) * 32 + gh[6] * 32 + (gh[7] + gh[8]) * 32 + (trchd_bytes + gh[23] * 4) * gh[18], SeekOrigin.Begin);
                        else if (gh[19] == 1)                                                          
                            fs.Seek((gh[2] + 1) * 32 + gh[6] * 32 + (gh[7] + gh[8]) * 32, SeekOrigin.Begin);
                        else
                        { MessageBox.Show("Read Segd file ERRO", "ERRO", MessageBoxButtons.OK); return null; }

                        int trc_num = gh[19] == 9 ? gh[20] : gh[18];                         

                        
                        byte[] trace;
                        for (int i = 0; i < trc_num; i++)
                        {
                            List temp = new List();
                            byte[] th1 = br.ReadBytes(trchd_bytes);
                            temp.Add(int.Parse(th1[4].ToString("x") + th1[5].ToString("x")));              
                            temp.Add(Convert.ToInt32(Convert.ToString(th1[20], 2).PadLeft(8, '0') +
                            Convert.ToString(th1[21], 2).PadLeft(8, '0') + Convert.ToString(th1[22], 2).PadLeft(8, '0'), 2));   
                            temp.Add(Convert.ToInt32(Convert.ToString(th1[23], 2).PadLeft(8, '0') +
                            Convert.ToString(th1[24], 2).PadLeft(8, '0') + Convert.ToString(th1[25], 2).PadLeft(8, '0'), 2));   
                            trace = br.ReadBytes(gh[23] * 4);
                            th.Add(temp);
                            traces.Add(trace);
                            
                        }

                        return new Tuple, List>, List>(gh, th, traces);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("SendPackageFunc()——读取文件错误" + ex.ToString());
                return null;
            }
        }

/////因为segd数据是大端字节序,要将道头也要转成大端字节序
        public void WriteSegy(string segdfile, string dir, char[] txh, dynamic[] bh, List> trch, int samples, long num, int seek, int trcheader_bytes, List traces)
        {
            string sgyfile = dir + @"\" + Path.GetFileNameWithoutExtension(segdfile) + ".sgy";
            if (File.Exists(sgyfile))
            {
                MessageBox.Show("文件已存在 !", " Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); return;
            }
            using (FileStream fs1 = new FileStream(sgyfile, FileMode.Create, FileAccess.ReadWrite))
            {
                using (BinaryWriter wr = new BinaryWriter(fs1))
                {

                    wr.Write(txh);                                                            

                    for (int i = 0; i < bh.Count(); i++)
                    { byte[] bb = BitConverter.GetBytes(bh[i]); Array.Reverse(bb); wr.Write(bb); }  

                    //fs.Seek(seek, SeekOrigin.Begin);
                    for (int i = 0; i < num; i++)
                    {
                        for (int k = 0; k < trch[i].Count(); k++)
                        {
                            byte[] bb = BitConverter.GetBytes(trch[i][k]);                     
                            Array.Reverse(bb);
                            wr.Write(bb);
                        }
                        //br.ReadBytes(trcheader_bytes);
                        wr.Write(traces[i]);                                 
                    }
                }
            }
        }

img

img

优化思路:
建议使用如下算法:
1、将循环体的值先保存到 DataTable 中
2、开启数据库事务
3、在数据库中建立临时表
4、使用 SqlBulkCopy 组件将 DataTable 的数据一次性导入到数据库的临时表
5、使用 SQL 语句处理临时表的数据
6、将处理的结果使用 SQL 查询出来
7、提交事务

所有需要多次与数据库交互的场景均可以使用上述机制处理,比循环交互快得多。

楼主有个方法没有上传,

img


从代码来看,感觉没啥问题,可以考虑改成多线程处理,MessageBox.Show可以改成输出至文本框:

            char[] Textheader = new char[3200];
            string dir = comboBox1.Text;
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < listBox_segd.Items.Count; i++)
            {
                if (tasks.Count==6)//控制线程数量
                {
                    Task.WaitAll(tasks.ToArray());
                    tasks = new List<Task>();
                }
                tasks.Add(Task.Run(() =>
                {
                    var segdHD = ReadSegd(listBox_segd.Items[i].ToString());
                    var segdhd2segyhd = SegdHeader2SegyHeader(segdHD.Item1, segdHD.Item2);
                    WriteSegy(listBox_segd.Items[i].ToString(), dir, Textheader, segdhd2segyhd.Item1,
                        segdhd2segyhd.Item2, segdhd2segyhd.Item3, segdhd2segyhd.Item4, segdhd2segyhd.Item5, segdhd2segyhd.Item6, segdHD.Item3);
                    segdHD = null;
                    segdhd2segyhd = null;
                }));
            }

测试一下路径为本地盘是否结果一样?
如果本地硬盘速度一样,监控一下主机的资源消耗,可能物理内存耗尽,使用磁盘swp交换了。
如果只是移动硬盘速度问题,大概率碰到windows 移动硬盘bug了。是win11吗?