遍历 DataTable 非常慢

Iterating through DataTable very slow

我对 webforms / windowsforms 的经验很少。去年,我作为一名开发人员开始了第一份工作,从事 MVC 网络开发,这就是我从那以后所做的一切。

我父亲最近让我创建一个简单的应用程序,为此我决定尝试 Windows 表单。该应用程序所做的是使用 OLEDB 将 excel sheet 文件读入 DataTable 并将其显示在 DataGridView:

完成后,每一列都与一组预定义的标签匹配,然后按以下格式写入 txt 文件:

@tag    (column value)

我作为示例使用的 excel 文件有大约 18k 行。使用 OLEDB 读取文件并将其绑定到 DataGridView 几乎是即时的(1/2 到 2 秒)。但是,当我将列与适当的标签匹配并生成所需的输出时,它会花费很长时间(5 分钟)。考虑到 DataTable 在这个阶段在内存中,这感觉是错误的。我不确定我是否会以极其低效的方式遍历 DataTable

下面是遍历 DataTable 以创建输出的代码:

private void GenerateOutputButton_Click(object sender, EventArgs e)
{
    OutputDisplayRichText.Clear();
    output = string.Empty;

    string selectedT = TComboBox.SelectedItem.ToString(),
           selectCDocdate = CDocdateComboBox.SelectedItem.ToString(),
           selectedCSubject = CSubjectCombobox.SelectedItem.ToString(),
           selectedTiff = TiffComboBox.SelectedItem.ToString();

    foreach (DataRow row in excelSheet.Rows)
    {
        if (TToken.Checked)
        {
            /*..removed code..*/
            output += "@T\t\t" + tempOutput + Environment.NewLine;
        }
        if (CDocdateToken.Checked)
        {
            string rowValue = row[selectCDocdate].ToString();
            string tempOutput = "@C Docdate\t\t" + rowValue + Environment.NewLine;
            output += tempOutput;
        }
        if (CSubjectToken.Checked)
        {
            string rowValue = row[selectedCSubject].ToString();
            string tempOutput = "@C Subject\t\t" + rowValue + Environment.NewLine;
            output += tempOutput;
        }
        if (DToken.Checked)
        {
            string rowValue = DTextBox.Text;
            string tempOutput = "@D \t\t" + rowValue + Environment.NewLine;
            output += tempOutput;
        }
        if (TiffFiles.Checked)
        {
            /*..removed code..*/
            output = TTextBox.Text + "{" + pageFromStr2 + "-" + pageToStr2 + "}.tif";
        }

        output += Environment.NewLine;
    }

    OutputDisplayTextBox.Text = output;
}
.net 中的

string 是不可变的,因此,每次使用 + 运算符连接两个 strings/values 时,都会创建一个新字符串并保留其他的 .net 将其从中删除记忆。为避免此问题,您可以使用 StringBuilder 实例,例如:

StringBuilder b = new StringBuilder();

foreach (DataRow row in excelSheet.Rows)
{
    if (TToken.Checked)
        b.AppendLine(string.Format("@T\t\t{0}", tempOutput));

    if (CDocdateToken.Checked)
        b.AppendLine(string.Format("@C Docdate\t\t{0}", row[selectCDocdate].ToString()));

    if (CSubjectToken.Checked)
        b.AppendLine(string.Format("@C Subject\t\t{0}", row[selectedCSubject].ToString())); 

    if (DToken.Checked)
        b.AppendLine(string.Format("@D \t\t{0}", DTextBox.Text));   

    if (TiffFiles.Checked)
        b.Append(TTextBox.Text + "{" + pageFromStr2 + "-" + pageToStr2 + "}.tif");

    b.AppendLine();
}

// generate everything in a single string.
output = b.ToString();

根据您的代码进行调整,因为我们没有它的详细信息。

字符串是不可变的,这意味着它们在内存中无法更改。您将看似大量的信息附加到字符串变量中 - 这会在内存中创建许多重复的字符串,占用越来越多的内存并降低应用程序的速度。

改用 StringBuilder class - 这是可变的。示例:

Stringbuilder builder = new StringBuilder();
builder.AppendLine("text"); // adds a new line to the StringBuilder

当需要输出文本时,在StringBuilder实例上调用.ToString()