簡體   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