【发布时间】:2013-08-08 01:14:50
【问题描述】:
我试图解决这个Question 中的问题,但我最终遇到了另一个问题
简而言之,这个问题是在询问如何将一个大文件逐块加载到 textBox 中,
所以在后台工作人员 Do_work 事件中我这样做了:
using (FileStream fs = new FileStream(@"myFilePath.txt", FileMode.Open, FileAccess.Read))
{
int bufferSize = 50;
byte[] c = null;
while (fs.Length - fs.Position > 0)
{
c = new byte[bufferSize];
fs.Read(c , 0,c.Length);
richTextBox1.AppendText(new string(UnicodeEncoding.ASCII.GetChars(c)));
}
}
这不起作用,因为 backgroundWorker 不能影响 UI 元素,我需要使用 BeginInvoke 来执行此操作。
所以我改了代码:
delegate void AddTextInvoker();
public void AddText()
{
using (FileStream fs = new FileStream(@"myFilePath.txt", FileMode.Open, FileAccess.Read))
{
int bufferSize = 50;
byte[] c = null;
while (fs.Length - fs.Position > 0)
{
c = new byte[bufferSize];
fs.Read(c , 0,c.Length);
richTextBox1.AppendText(new string(UnicodeEncoding.ASCII.GetChars(c)));
}
}
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.BeginInvoke(new AddTextInvoker(AddText));
}
这段代码有两个问题。
1-附加文本需要越来越长的时间(我认为由于字符串不变性,随着时间的推移替换文本需要更长的时间)
2- 在每次添加时,richTextBox 都会向下滚动到导致应用程序挂起的末尾。
问题是如何停止滚动和应用程序挂起?
在这里我能做些什么来增强字符串连接?
编辑:经过一些测试并使用马特的答案,我得到了这个:
public void AddText()
{
using (FileStream fs = new FileStream(@"myFilePath.txt", FileMode.Open, FileAccess.Read))
{
int bufferSize = 50;
byte[] c = null;
while (fs.Length - fs.Position > 0)
{
c = new byte[bufferSize];
fs.Read(c , 0,c.Length);
string newText = new string(UnicodeEncoding.ASCII.GetChars(c));
this.BeginInvoke((Action)(() => richTextBox1.AppendText(newText)));
Thread.Sleep(5000); // here
}
}
}
当加载暂停时,我可以毫无问题地读写或挂起,一旦文本超过richTextBox 大小,加载将向下滚动并阻止我继续。
【问题讨论】:
-
粘贴其余代码,死锁不在这里。
-
要以这种方式解决它,我宁愿在
worker_DoWork中使用加载文件循环并从那里调用richTextBox1.BeginInvoke 以将另一块文本发送到文本控件。 -
您在主线程上调用
AddText,这违背了BackgroundWorker的目的。一旦数据在内存中,您需要调用 Dispatcher。我希望你的机器可以处理 1GB+ 的文本字符串。 -
您使用的是哪个 .NET 版本?
-
@Romoku 我正在使用 .NET4
标签: c# string winforms asynchronous background