如何在C#中读取大文本文件?

时间:2019-07-07 08:40:32

标签: c# winforms file readfile

我有一个获胜表格,我想阅读一个文本文件并将其显示在列表框中,但是当我尝试在几秒钟后尝试以1-3mb的大小加载文件时出现问题:

  

托管调试助手“ ContextSwitchDeadlock”:“ CLR在60秒钟内无法从COM上下文0x149cf10过渡到COM上下文0x149ce58。拥有目标上下文/公寓的线程很可能要么执行非泵送等待,要么处理很长时间运行的操作而不泵送Windows消息。这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随时间不断累积。为避免此问题,所有单线程单元(STA)线程都应使用泵送等待原语(例如CoWaitForMultipleHandles),并在长时间运行的操作中定期泵送消息。'

这是我的代码:

private void Button7_Click(object sender, EventArgs e)
    {
        openFileDialog = new OpenFileDialog();
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            StreamReader sr = new StreamReader(openFileDialog.FileName);
            var emails = sr.ReadToEnd();
            foreach (var items in emails)
            {
                aFlistBoxEmail.Items.Add(items);
            }
        }
    }

我也使用此解决方案,但没有帮助: enter link description here

5 个答案:

答案 0 :(得分:1)

您可以尝试一次读取所有行:

private async void Button7_Click(object sender, EventArgs e)
{
    openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
        aFlistBoxEmail.DataSource = File.ReadAllLines(openFileDialog.FileName);
}

答案 1 :(得分:0)

您的单击处理程序在UI线程上执行,这也恰好为您的应用程序运行消息泵。由于您的处理程序要花很长时间运行,因此它会使您的应用程序在可能无法接受的时间内对UI和系统事件无响应。

您可以通过使逻辑异步来解决问题。

private async Task Button7_Click(object sender, EventArgs e)
{
    openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
    {
        StreamReader sr = new StreamReader(openFileDialog.FileName);
        var emails = await sr.ReadToEndAsync();
        foreach (var items in emails)
        {
            aFlistBoxEmail.Items.Add(items);
        }
    }
}

答案 2 :(得分:0)

当有长时间运行的进程时,由于长时间运行的进程位于UI线程内部,因此应用程序将自动进入非响应模式,最好通过await&async使用asyn编程,这将有助于运行长时间运行的活动进入一个单独的线程中,它不会破坏UI线程。我的示例代码如下。

private async void Button7_Click(object sender, EventArgs e)
{
    openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
    {
        StreamReader sr = new StreamReader(openFileDialog.FileName);
        var emails =  await sr.ReadToEndAsync();
        foreach (var items in emails)
        {
            aFlistBoxEmail.Items.Add(items);
        }
    }
}

文件读取部分可以移至其他功能,以便提供更多模块化。

答案 3 :(得分:0)

您为什么要这样做呢?您的代码将文本文件中的每个字符添加为列表框中的单独条目,对于3 MB的文件,它将有很多条目,您是否不需要先将文本解析为特定值或类?如果您要尝试从文件中读取电子邮件,请按照以下方式分割文件,例如string.Split('\n');,方法是分离每封电子​​邮件,然后使用MailAddress中的System.Net.Mail.MailAddress类解析它们>

答案 4 :(得分:0)

这不一定意味着您有问题,但是由于您正在使用UI的主线程,因此它可能会引起问题-因此您的应用将一直停留到读者完成其工作并且文件太重正在收到此错误。您可以在以下位置将其关闭:

调试>窗口>例外设置>托管调试助手(展开)>禁用“ ContextSwitchDeadlock”

最好将此任务放入线程或任务中,并确保在失败的情况下(或using语句)也可以尝试在方法内捕获 同时(直到文件阅读器完成),您可以在UI上显示一条消息,指出“应用程序忙”或类似内容。

SELECT name 
    , department
    , jointime 
    , employeeId
    FROM employee where  department='Mechanical'
    GROUP BY  name
            , department
            , jointime 
            , employeeId