繁体   English   中英

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

[英]how to read big text files in C#?

我有一个 win 表单,我想读取一个文本文件并将其显示在列表框中,但是当我尝试在几秒钟后加载 1-3mb 大小的文件时出现问题,它抛出此异常:

托管调试助手“ContextSwitchDeadlock”:“CLR 无法从 COM 上下文 0x149cf10 转换到 COM 上下文 0x149ce58 60 秒。 拥有目标上下文/单元的线程最有可能执行非泵等待或处理非常长时间运行的操作而不泵送 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);
            }
        }
    }

我也使用此解决方案但没有帮助: 在此处输入链接描述

您的点击处理程序在 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);
        }
    }
}

当有长时间运行的进程时,应用程序将自动进入非响应模式,因为长时间运行的进程在 UI 线程内,最好使用 await & async 使用异步编程,这将有助于运行长时间运行的活动进入一个单独的线程,它不会破坏 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 MB 的文件,它将是很多条目,您不需要先将文本解析为特定值或类吗? 如果您尝试从文件中读取电子邮件,请像这样拆分文件,例如string.Split('\\n'); 以某种方式将每封电子邮件分开,然后使用System.Net.Mail.MailAddressMailAddress类解析它们

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

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

这并不一定意味着你有问题,但它可能会导致问题,因为你正在 UI 的主线程上工作 - 所以你的应用程序将被卡住,直到读者完成它的工作,因为它是一个沉重的文件你得到这个错误。 您可以在以下位置关闭此功能:

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

将此任务放在线程或任务中是个好主意,并确保您也尝试在方法内部捕获,以防万一它失败(或使用语句),同时(直到文件阅读器完成)您可以显示在UI 一条消息说“应用程序正忙”或类似的东西。

Thread thread = new Thread(Butoon_Click(sender, ev));
thread.IsBackground = true;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM