简体   繁体   English

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

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

I have a win Form and I want to read a text file and show it in list Box but there is problem when i try to load file with 1-3mb size after a few seconds its throw this exception:我有一个 win 表单,我想读取一个文本文件并将其显示在列表框中,但是当我尝试在几秒钟后加载 1-3mb 大小的文件时出现问题,它抛出此异常:

Managed Debugging Assistant 'ContextSwitchDeadlock' : 'The CLR has been unable to transition from COM context 0x149cf10 to COM context 0x149ce58 for 60 seconds.托管调试助手“ContextSwitchDeadlock”:“CLR 无法从 COM 上下文 0x149cf10 转换到 COM 上下文 0x149ce58 60 秒。 The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages.拥有目标上下文/单元的线程最有可能执行非泵等待或处理非常长时间运行的操作而不泵送 Windows 消息。 This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time.这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随着时间的推移不断累积。 To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.'为避免此问题,所有单线程单元 (STA) 线程都应使用泵等待原语(例如 CoWaitForMultipleHandles)并在长时间运行的操作期间定期泵送消息。

and here is my code:这是我的代码:

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);
            }
        }
    }

also i use this solution but didnt help: enter link description here我也使用此解决方案但没有帮助: 在此处输入链接描述

Your click handler executes on the UI thread, which also happens to run the message pump for your application.您的点击处理程序在 UI 线程上执行,它也恰好为您的应用程序运行消息泵。 Since your handler takes so long to run, it makes your application nonresponsive to UI and system events for a period that is probably unacceptable.由于您的处理程序需要很长时间才能运行,这会使您的应用程序在一段时间内对 UI 和系统事件无响应,这可能是不可接受的。

You can remedy the problem by making your logic async.您可以通过使逻辑异步来解决问题。

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);
        }
    }
}

When there are long running process, then automatically the application will go into non responsive mode , because the long running process is inside the UI thread, Its better to use the asyn programming using await & async , this will help to run the long running activities into a seperate thread and it wont break the UI thread.当有长时间运行的进程时,应用程序将自动进入非响应模式,因为长时间运行的进程在 UI 线程内,最好使用 await & async 使用异步编程,这将有助于运行长时间运行的活动进入一个单独的线程,它不会破坏 UI 线程。 My sample code is given below.我的示例代码如下。

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);
        }
    }
}

The the file reading part can be moved to another function so that it can give more modulatiry.文件读取部分可以移动到另一个功能,以便它可以提供更多的模块化。

Why are you doing this exactly?你为什么要这样做? your code adds every single character in the text file as a separate entry in the list box, with a 3 MB file it will be a lot of entries, don't you need to parse the text to a specific value or a class first?您的代码将文本文件中的每个字符添加为列表框中的一个单独条目,对于 3 MB 的文件,它将是很多条目,您不需要先将文本解析为特定值或类吗? if you're trying to read emails from a file split the file like this for example string.Split('\\n');如果您尝试从文件中读取电子邮件,请像这样拆分文件,例如string.Split('\\n'); in a way you separate each email and then parse them using the MailAddress Class from System.Net.Mail.MailAddress以某种方式将每封电子邮件分开,然后使用System.Net.Mail.MailAddressMailAddress类解析它们

You can try reading all lines at once :您可以尝试一次阅读所有行:

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

it doesn't necessarily mean you have an issue but it can cause issues since you're working on the main thread of the UI - so your app will be stuck until the reader finishes it's work and since it's a heavy file you're getting this error.这并不一定意味着你有问题,但它可能会导致问题,因为你正在 UI 的主线程上工作 - 所以你的应用程序将被卡住,直到读者完成它的工作,因为它是一个沉重的文件你得到这个错误。 you can switch this off in:您可以在以下位置关闭此功能:

Debug > windows > Exceptions settings > Managed Debugging Assistants (expand) > disable "ContextSwitchDeadlock"调试 > 窗口 > 异常设置 > 托管调试助手(展开)> 禁用“ContextSwitchDeadlock”

it's a good idea to put this task in a thread or a task and make sure you have try catch INSIDE the method as well in case it fails (or a using statement) and meanwhile (until the file reader finishes) you can display on the UI a message saying "app is busy" or something similar.将此任务放在线程或任务中是个好主意,并确保您也尝试在方法内部捕获,以防万一它失败(或使用语句),同时(直到文件阅读器完成)您可以显示在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