該錯誤可能是在
label5.Text = i.ToString();
label5.Update();
只是爲了測試我寫的是這樣的:
for (int i = 0; i < int.MaxValue; i++)
{
label1.Text = i.ToString();
label1.Update();
}
該應用程序凍結圍繞16000-18000(Windows 7的臨SP1 x64,運行x86和x64的應用程序)。
可能發生的情況是,通過在應用程序的主線程中運行長操作,可以停止窗口的消息隊列,並在某個點凍結。你可以看到,這是通過添加
Application.DoEvents();
,而不是
label5.Update();
問題,但即使這是一個錯誤的解決方案。正確的解決方案是移動複製在另一個線程,並更新每x毫秒的控制下,使用Invoke
方法(因爲你是在輔助線程),
例如:
public void Copy(string source, string dest)
{
const int updateMilliseconds = 100;
int index = 0;
int i = 0;
StreamWriter writefile = null;
try
{
using (StreamReader readfile = new StreamReader(source))
{
writefile = new StreamWriter(dest + index);
// Initial value "back in time". Forces initial update
int milliseconds = unchecked(Environment.TickCount - updateMilliseconds);
string content;
while ((content = readfile.ReadLine()) != null)
{
writefile.Write(content);
writefile.Write("\r\n"); // Splitted to remove a string concatenation
i++;
if (i % 1000000 == 0)
{
index++;
writefile.Dispose();
writefile = new StreamWriter(dest + index);
// Force update
milliseconds = unchecked(milliseconds - updateMilliseconds);
}
int milliseconds2 = Environment.TickCount;
int diff = unchecked(milliseconds2 - milliseconds);
if (diff >= updateMilliseconds)
{
milliseconds = milliseconds2;
Invoke((Action)(() => label5.Text = string.Format("File {0}, line {1}", index, i)));
}
}
}
}
finally
{
if (writefile != null)
{
writefile.Dispose();
}
}
// Last update
Invoke((Action)(() => label5.Text = string.Format("File {0}, line {1} Finished", index, i)));
}
並用稱之爲:
var thread = new Thread(() => Copy(@"C:\Temp\lst.txt", @"C:\Temp\output"));
thread.Start();
說明它將如何寫label5
每100毫秒,再加上一旦開頭(通過設置milliseconds
「時光倒流」的初始值),每次輸出文件的變化d(通過設置milliseconds
的值「回到過去」)以及處理完所有內容後。
通過使用BackgroundWorker
類可以編寫一個更正確的示例,該類明確存在於此場景中。它有一個事件,ProgressChanged
,可以訂閱更新窗口。
事情是這樣的:
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerAsync(new string[] { @"C:\Temp\lst.txt", @"C:\Temp\output" });
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
string[] arguments = (string[])e.Argument;
string source = arguments[0];
string dest = arguments[1];
const int updateMilliseconds = 100;
int index = 0;
int i = 0;
StreamWriter writefile = null;
try
{
using (StreamReader readfile = new StreamReader(source))
{
writefile = new StreamWriter(dest + index);
// Initial value "back in time". Forces initial update
int milliseconds = unchecked(Environment.TickCount - updateMilliseconds);
string content;
while ((content = readfile.ReadLine()) != null)
{
writefile.Write(content);
writefile.Write("\r\n"); // Splitted to remove a string concatenation
i++;
if (i % 1000000 == 0)
{
index++;
writefile.Dispose();
writefile = new StreamWriter(dest + index);
// Force update
milliseconds = unchecked(milliseconds - updateMilliseconds);
}
int milliseconds2 = Environment.TickCount;
int diff = unchecked(milliseconds2 - milliseconds);
if (diff >= updateMilliseconds)
{
milliseconds = milliseconds2;
worker.ReportProgress(0, new int[] { index, i });
}
}
}
}
finally
{
if (writefile != null)
{
writefile.Dispose();
}
}
// For the RunWorkerCompleted
e.Result = new int[] { index, i };
}
void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int[] state = (int[])e.UserState;
label5.Text = string.Format("File {0}, line {1}", state[0], state[1]);
}
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int[] state = (int[])e.Result;
label5.Text = string.Format("File {0}, line {1} Finished", state[0], state[1]);
}
該文件可能有一個超長線...例如,如果文件中有一條線長100MB,那麼你可以有問題。 – xanatos
xanatos是對的。將行長度輸出到控制檯('if(length> 100000)print(length)')。 – usr
使用'Read'方法。指定要讀取的字符數量:'char [] ch = new char [100000];'然後用'readfile.Read(ch,0,ch.Length);'填充它。最後把填充的char []('ch')寫入文件 –