我使用RichTextBox测试REGEX表达式,代码如下:
rtbMain.SelectAll();
rtbMain.SelectionColor = Color.Black;
rtbMain.SelectionBackColor = Color.White;
Regex regex = new Regex(txtRegexPattern.Text, regexOptions);
Match matches = regex.Match(txtTest.Text);
while (matches.Success)
{
rtbMain.Select(matches.Index, match.Length);
rtbMain.SelectionColor = Color.Red;
rtbMain.SelectionBackColor = Color.Black;
}
但是,只要突出显示超过几千(1000+)个字符,此方法就会变得太慢。我知道我可以延迟处理,所以代码让用户有机会输入整个正则表达式,但我认为RichTextBox突出显示工作太慢。
我搜索了谷歌寻找加速当前解决方案的不同方法和方法,但我没有运气。我注意到有一些文本编辑器允许“语法高亮”(如ScintillNET,Avalon,...)但他们使用XML作为输入,所以我认为将它们用于我的项目(在每个KeyUp事件上生成XML)将不会是“最佳实践”。
我在这里找到并测试了一个“快速彩色文本框”:https://github.com/PavelTorgashov/FastColoredTextBox ...但是这个问题是它在使用自己的新行和制表符时取代了粘贴内容,我不能在REGEX测试仪中使用它。
是否有更快的方法来突出显示所有匹配项,可能使用不同的用户控件?
编辑:
方法1:生成基础RTF文档会更快吗?我试过但是在使用特殊字符方面遇到了一些问题,所以我可以测试整个文档的突出显示,但它似乎在一行中使用普通字符的速度非常快。我暂停工作,因为我读到构建RTF可能非常困难,我想我不能使用现有的RTF库。
方法2:我只能获得RichTextBox的显示部分,所以我想只强调那部分。我想这会显着减少处理(取决于RTB大小),但每次用户滚动时我都需要触发突出显示;我不确定这会运作良好并创造一个体面的用户体验,所以还没有尝试过。
有人会推荐上述任何方法,还是其他方法?
答案 0 :(得分:2)
<强>首先强>
RichTextBox有一个固有的问题:它在.NET中非常慢。我找到了一个解决方案,如何使它快120倍。可能是你试试看:C# RichEditBox has extremely slow performance (4 minutes loading) SOLVED
<强>第二强>
从头开始构建RTF代码是最快的解决方案。看看我在codeproject上的文章。有一个可重用的RTF构建器类:http://www.codeproject.com/Articles/23513/SQL-Editor-for-Database-Developers
答案 1 :(得分:1)
请在http://www.codeproject.com/Articles/3669/Expresso-A-Tool-for-Building-and-Testing-Regular-E
查看Expresso我多年来一直在使用这个程序来编辑和评估正则表达式。
答案 2 :(得分:1)
我怀疑您是否以错误的方式设置了While
循环。
尝试这样的事情:( 未经测试,但会告诉您如何解决此问题)
rtbMain.SelectAll();
rtbMain.SelectionColor = Color.Black;
rtbMain.SelectionBackColor = Color.White;
Regex regex = new Regex(txtRegexPattern.Text, regexOptions);
MatchCollection matches = regex.Matches(txtTest.Text);
if(matches.Count > 0)
{
foreach(Match m in matches)
{
rtbMain.Select(m.Index, m.Length);
rtbMain.SelectionColor = Color.Red;
rtbMain.SelectionBackColor = Color.Black;
}
}
else
{
Debug.Print("No matches found"); // See "Output" Window
}
修改强>
我做了一些与突出显示RTF文本相关的解决方法,我发现的第一件事就是这个过程主要花费的时间是:
rtbMain.SelectionColor = Color.Red;
rtbMain.SelectionBackColor = Color.Black;
我尝试使用SelectionStart
和SelectionEnd
属性选择文本而不是.Select()
,但未观察到任何更改。
关于与构造等效RTF相关的第一点,我也试过了,但很难构造一个等效的RTF,因为那里有很多需要处理的东西。如果可以完成,则处理时间将在&lt;超过31k匹配的1.5秒(对特定样本进行基本测试的结果)。
所以,我建议你通过 THREADING 来完成它,并在两个主题中拆分任务:
以下是一个示例源代码: (对于最糟糕的情况,我发现大约31341场比赛,并且过程需要4秒才能突出显示)
// declare variables either globally or in the same method
MatchCollection mcoll;
Stopwatch s;
int callbackCount = 0;
List<Match> m1 = null;
List<Match> m2 = null;
private void btnHighlight_Click(object sender, EventArgs e)
{
//reset any exisiting formatting
rtbMain.SelectAll();
rtbMain.SelectionBackColor = Color.White;
rtbMain.SelectionColor = Color.Black;
rtbMain.DeselectAll();
s = new Stopwatch();
s.Start();
Regex re = new Regex(@"(.)", RegexOptions.Compiled); // Notice COMPILED option
mcoll = re.Matches(rtbMain.Text);
// Break MatchCollection object into List<Matches> which is exactly half in size
m1 = new List<Match>(mcoll.Count / 2);
m2 = new List<Match>(mcoll.Count / 2);
for (int k = 0; k < mcoll.Count; k++)
{
if (k < mcoll.Count / 2)
m1.Add(mcoll[k]);
else
m2.Add(mcoll[k]);
}
Thread backgroundThread1 = new Thread(new ThreadStart(() => {
match1(null, null);
}));
backgroundThread1.Start();
Thread backgroundThread2 = new Thread(new ThreadStart(() =>
{
match2(null, null);
}));
backgroundThread2.Start();
}
public void match1(object obj, EventArgs e)
{
for (int i=0; i < m1.Count; i += 1)
{
if (rtbMain.InvokeRequired)
{
EventHandler d = new EventHandler(match1);
rtbMain.Invoke(d);
}
else
{
rtbMain.Select(m1[i].Index, m1[i].Length);
rtbMain.SelectionBackColor = Color.Black;
rtbMain.SelectionColor = Color.Red;
}
}
stopTimer();
}
public void match2(object obj, EventArgs e)
{
for (int j=0; j < m2.Count; j += 1)
{
if (rtbMain.InvokeRequired)
{
EventHandler d = new EventHandler(match2);
rtbMain.Invoke(d);
}
else
{
rtbMain.Select(m2[j].Index, m2[j].Length);
rtbMain.SelectionBackColor = Color.Black;
rtbMain.SelectionColor = Color.Red;
}
}
stopTimer();
}
void stopTimer()
{
callbackCount++;
if (callbackCount == 2) // 2 because I am using two threads.
{
s.Stop();
// Check Output Window
Debug.Print("Evaluated in : " + s.Elapsed.Seconds.ToString());
}
}
因为你发布它需要大约30秒来操作,希望4秒是可以忍受的,并且用户可以通过某些加载屏幕使用,因为其他在线转换器就像Rubular和DerekSlager's .Net regex tester那样。 / p>
不要忘记查看Why Regex.Compiled preferred。