mfa*_*mfa 6 .net c# performance backgroundworker winforms
我正在尝试创建一个ac#WinForms应用程序,用于搜索和突出显示RichTextBox中的文本.我创建了两种搜索方法:一种在GUI线程中运行,另一种在BackGroundWorker中运行.两种方法中的逻辑基本相同.但是,BGW中的代码运行速度要慢得多.
请看下面的结果:
搜索常用关键字的0.25MB文本文件:GUI:2.9s - BGW:7.0s
1MB搜索常用关键字的文本文件:GUI:14.1s - BGW:71.4s
5MB搜索常用关键字的文本文件:GUI:172s - BGW:1545s
我觉得奇怪的是,这两种方法所花费的时间之间的关系不是关于搜索大小的线性关系.
该应用程序将用于搜索最大10MB的文件,因此这很重要.我想使用后台工作程序,以便用户可以看到进度并在执行搜索时继续读取文件.
请参阅以下两种方法的代码:
// background search thread
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
RichTextBox rtb = new RichTextBox();
RichTextBox results = new RichTextBox();
rtb.Rtf = e.Argument as string; //recive text to be searched
int hits = 0; // track number of hits
int pos = 0; // track position in rtb
int i = 0; // trach current line number for progress report
string lowerT = searchTerm.ToLowerInvariant();
string lowerl = "";
int n = 0;
int len = searchTerm.Length;
foreach (string l in rtb.Lines)
{
lowerl = l.ToLowerInvariant();
n = lowerl.IndexOf(lowerT);
if (n > -1)
{
while (n > -1) //if found sterm highlight instances
{
hits++; //incriment hits
//hilight term
rtb.SelectionStart = pos + n;
rtb.SelectionLength = len;
rtb.SelectionBackColor = Color.Yellow;
rtb.SelectionColor = Color.Black;
//find next
n = lowerl.IndexOf(lowerT, n + len);
}
searchRes.Add(pos); // add positon of hit to results list
//add rtb formatted text to results rtb
rtb.SelectionStart = pos;
rtb.SelectionLength = l.Length;
results.SelectedRtf = rtb.SelectedRtf;
results.AppendText(Environment.NewLine);
}
pos += l.Length + 1; //incriment position
//worker.ReportProgress(++i);
}
string[] res = {rtb.Rtf,results.Rtf,hits.ToString()};
e.Result = res;
}
// old non threaded search method
public void OldSearch(string sTerm)
{
int hits = 0; // track number of hits
int pos = 0; // track position in rtb
int oldPos = richTextBox1.SelectionStart; //save current positin in rtb
int oldLen = richTextBox1.SelectionLength;
string lowerT = sTerm.ToLowerInvariant();
sTime = 0;
System.Threading.Timer tmr = new System.Threading.Timer(new TimerCallback(TimerTask), null, 0, 100);
if (sTerm.Length > 0)
{
//clear old search
ReloadFile();
richTextBox4.Clear();
searchRes = new List<int>();
//open results pane
label1.Text = "Searching for \"" + sTerm + "\"...";
splitContainer1.Panel2Collapsed = false;
frmFind.Focus();
frmFind.ShowProgress(true);
foreach (string l in richTextBox1.Lines)
{
string lowerl = l.ToLowerInvariant();
int n = lowerl.IndexOf(lowerT);
if (n > -1)
{
while (n > -1) //if found sterm highlight instances
{
hits++; //incriment hits
//hilight term
richTextBox1.SelectionStart = pos + n;
richTextBox1.SelectionLength = sTerm.Length;
richTextBox1.SelectionBackColor = Color.Yellow;
richTextBox1.SelectionColor = Color.Black;
//find next
n = lowerl.IndexOf(lowerT, n + sTerm.Length);
}
searchRes.Add(pos);
richTextBox1.SelectionStart = pos;
richTextBox1.SelectionLength = l.Length;
richTextBox4.SelectedRtf = richTextBox1.SelectedRtf;
richTextBox4.AppendText(Environment.NewLine);
}
pos += l.Length + 1; //incriment position
}
tmr.Dispose();
float time = (float)sTime / 10;
label1.Text = "Search for \"" + sTerm + "\": Found " + hits + " instances in " + time + " seconds.";
richTextBox4.SelectionStart = 0;
richTextBox1.SelectionStart = oldPos;
richTextBox1.SelectionLength = oldLen;
richTextBox1.Focus();
frmFind.ShowProgress(false);
}
}
Run Code Online (Sandbox Code Playgroud)
笔记:
ReportProgress我已经评论过这一行.我这样做而不是百分比的原因是计算得出百分比差别很大.实际上这种方式更快通常减慢 Winform 速度的一件事是与 UI 线程同步。如果 ReportProgress 这样做(我不知道,但我猜它必须这样做)并且你调用它太频繁(比如每秒 100-1000 次或更多),它会由于各种阻塞问题而减慢一切直至停止那将会发生。
尝试删除 UI 和后台线程之间的任何交互,如果有帮助,请恢复交互,但让它发生的频率要低得多,例如每秒 1-100 次。
另外,我不确定,但如果您传递对控件对象的引用,它可能仍然由 UI 线程拥有,并且来自另一个线程的每次交互也可能导致同步问题(以及与实际表单控件的交互)会抛出异常)。
| 归档时间: |
|
| 查看次数: |
5275 次 |
| 最近记录: |