如何在 C# 中读取大文本文件?
how to read big text files in C#?
我有一个 win Form,我想读取一个文本文件并将其显示在列表框中,但是当我尝试加载 1-3mb 大小的文件时出现问题几秒钟后抛出此异常:
Managed Debugging Assistant 'ContextSwitchDeadlock' : 'The CLR has been unable to transition from COM context 0x149cf10 to COM context 0x149ce58 for 60 seconds. 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. 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.'
这是我的代码:
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
您的点击处理程序在 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);
}
}
}
当有长运行ning进程时,应用程序会自动进入非响应模式,因为长运行ning进程在UI线程内,更好使用 await 和 async 的异步编程,这将有助于 运行 长 运行ning 活动进入一个单独的线程,并且不会破坏 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 的文件,它将有很多条目,您不需要将文本解析为特定值或 class 首先?如果您尝试从文件中读取电子邮件,请像这样拆分文件,例如 string.Split('\n');
以某种方式分隔每封电子邮件,然后使用 MailAddress
Class 来自 [=12] 解析它们=]
您可以尝试一次阅读所有行:
private async void Button7_Click(object sender, EventArgs e)
{
openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == DialogResult.OK)
aFlistBoxEmail.DataSource = File.ReadAllLines(openFileDialog.FileName);
}
这并不一定意味着你有问题,但它可能会导致问题,因为你正在处理 UI 的主线程 - 所以你的应用程序将被卡住,直到 reader完成它的工作,因为它是一个很重的文件,所以你会收到这个错误。您可以在以下位置关闭此功能:
调试 > windows > 异常设置 > 托管调试助手(展开)> 禁用 "ContextSwitchDeadlock"
最好将此任务放在线程或任务中,并确保在方法内也有 try catch 以防失败(或 using 语句)
同时(直到文件 reader 完成)你可以在 UI 上显示一条消息说 "app is busy" 或类似的东西。
Thread thread = new Thread(Butoon_Click(sender, ev));
thread.IsBackground = true;
我有一个 win Form,我想读取一个文本文件并将其显示在列表框中,但是当我尝试加载 1-3mb 大小的文件时出现问题几秒钟后抛出此异常:
Managed Debugging Assistant 'ContextSwitchDeadlock' : 'The CLR has been unable to transition from COM context 0x149cf10 to COM context 0x149ce58 for 60 seconds. 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. 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.'
这是我的代码:
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
您的点击处理程序在 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);
}
}
}
当有长运行ning进程时,应用程序会自动进入非响应模式,因为长运行ning进程在UI线程内,更好使用 await 和 async 的异步编程,这将有助于 运行 长 运行ning 活动进入一个单独的线程,并且不会破坏 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 的文件,它将有很多条目,您不需要将文本解析为特定值或 class 首先?如果您尝试从文件中读取电子邮件,请像这样拆分文件,例如 string.Split('\n');
以某种方式分隔每封电子邮件,然后使用 MailAddress
Class 来自 [=12] 解析它们=]
您可以尝试一次阅读所有行:
private async void Button7_Click(object sender, EventArgs e)
{
openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == DialogResult.OK)
aFlistBoxEmail.DataSource = File.ReadAllLines(openFileDialog.FileName);
}
这并不一定意味着你有问题,但它可能会导致问题,因为你正在处理 UI 的主线程 - 所以你的应用程序将被卡住,直到 reader完成它的工作,因为它是一个很重的文件,所以你会收到这个错误。您可以在以下位置关闭此功能:
调试 > windows > 异常设置 > 托管调试助手(展开)> 禁用 "ContextSwitchDeadlock"
最好将此任务放在线程或任务中,并确保在方法内也有 try catch 以防失败(或 using 语句) 同时(直到文件 reader 完成)你可以在 UI 上显示一条消息说 "app is busy" 或类似的东西。
Thread thread = new Thread(Butoon_Click(sender, ev));
thread.IsBackground = true;