Я пытаюсь создать приложение WinForms на C #, которое ищет и выделяет текст в RichTextBox. Я создал два метода поиска: один работает в потоке графического интерфейса пользователя, а другой - в BackGroundWorker. Логика в обоих методах по сути идентична. Однако код в BGW работает значительно медленнее.
См. Результаты ниже:
0,25 МБ Текстовый файл с поиском по общему ключевому слову: GUI: 2,9 с - BGW: 7,0 с
1 МБ Текстовый файл для поиска по общему ключевому слову: GUI: 14.1s - BGW: 71.4s
5 МБ Текстовый файл для поиска по общему ключевому слову: GUI: 172s - BGW: 1545s
Мне кажется странным, что соотношение между временем, затрачиваемым на эти два метода, не зависит от размера поиска.
Приложение будет использоваться для поиска файлов размером до 10 МБ, поэтому важно, чтобы это выполнялось быстро. Я хотел использовать фонового рабочего, чтобы пользователь мог видеть прогресс и продолжать читать файл, пока выполняется поиск.
См. Код для двух методов ниже:
// 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();
//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);
}
}
ПРИМЕЧАНИЯ:
ReportProgress
Я закомментировал эту строку. Причина, по которой я делаю это таким образом, а не в процентах, заключается в том, что расчет процента имел большое значение. На самом деле это быстрее