c#-有没有更快捷的方法突出显示正则表达式匹配项(RichTextBox)
我使用RichTextBox测试正则表达式,代码如下:c#-有没有更快捷的方法突出显示正则表达式匹配项(RichTextBox),c#,winforms,performance,richtextbox,highlight,C#,Winforms,Performance,Richtextbox,Highlight,我使用RichTextBox测试正则表达式,代码如下: 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.Su
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高亮显示的工作速度太慢了
我在谷歌上搜索了不同的方法和途径来加速当前的解决方案,但我运气不好。我注意到有一些文本编辑器允许“语法突出显示”(如闪烁、Avalon等),但它们使用XML作为输入,因此我认为在我的项目中使用它们(在每个键控事件上生成XML)不是“最佳实践”
我在这里找到并测试了一个“快速着色文本框”:……但这个文本框的问题是,它在使用自己的新行和制表符时替换了粘贴内容,而我无法在REGEX tester中使用它
有没有更快的方法来突出显示所有匹配项,或者使用不同的用户控件
编辑:
方法1:生成底层RTF文档会更快吗?我试过了,但在特殊字符方面遇到了一些问题,所以我可以测试整个文档的突出显示,但在一行中使用普通字符时,它似乎工作得相当快。我暂停了这方面的工作,因为我读到构建RTF非常困难,我想我不能使用任何现有的RTF库
方法2:我只能得到RichTextBox显示的部分,所以我想只突出显示该部分。我想这将显著减少处理(取决于RTB大小),但我需要在每次用户滚动时触发高亮显示;我不确定这是否能很好地工作并创造出一个良好的用户体验,所以还没有尝试过
是否有人推荐上述方法或其他方法?请访问Expresso
多年来,我一直在使用此程序编辑和评估正则表达式。我怀疑您是否以不正确的方式设置了
循环
尝试以下内容:(未经测试,但将为您提供解决此问题的方法)
编辑
我做了一些与突出显示RTF文本相关的变通方法,我发现这个过程所花费的时间主要是以下几行:
rtbMain.SelectionColor = Color.Red;
rtbMain.SelectionBackColor = Color.Black;
我尝试使用SelectionStart
和SelectionEnd
属性来选择文本,但没有发现任何更改
关于你的第一点,关于构造等价的RTF,我也尝试过,但是构造等价的RTF是困难的,因为有很多东西需要处理。如果能够完成,则处理时间约为<1.5秒,超过31k次匹配(特定样品的基本测试结果)
因此,我建议您通过线程化并将任务拆分为两个线程:
下面是一个示例源代码:
(在最坏的情况下,我发现大约31341个匹配项,这个过程花了4秒钟突出显示)
//全局或在同一方法中声明变量
麦考尔;
秒表;
int callbackCount=0;
列表m1=空;
列表m2=空;
private void btnHighlight\u单击(对象发送者,事件参数e)
{
//重置任何现有格式
rtbMain.SelectAll();
rtbMain.SelectionBackColor=Color.White;
rtbMain.SelectionColor=Color.Black;
rtbMain.deceloseall();
s=新秒表();
s、 Start();
Regex re=new Regex(@“(.)”,RegexOptions.Compiled);//注意编译选项
mcoll=re.Matches(rtbMain.Text);
//将MatchCollection对象拆分为大小正好为一半的列表
m1=新列表(mcoll.Count/2);
m2=新列表(mcoll.Count/2);
for(int k=0;k{
match1(null,null);
}));
backgroundThread1.Start();
线程背景thread2=新线程(新线程开始(()=>
{
match2(null,null);
}));
backgroundThread2.Start();
}
公共无效匹配1(对象对象对象、事件参数)
{
对于(int i=0;i
由于您发布的操作大约需要30秒,所以希望4秒是可以忍受的,用户可以通过一些加载屏幕参与,就像其他在线转换器一样。
rtbMain.SelectionColor = Color.Red;
rtbMain.SelectionBackColor = Color.Black;
// 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());
}
}