本文共 7810 字,大约阅读时间需要 26 分钟。
首先说明一下,我这里的异步方式是指获取代码文件的时候,采用的是异步方式,其原因就是我要搜索C:\Program Files文件夹下面的含有关键字为scyGroupBox的代码文件。那么,从我的描述就可以知道,这是一个相当费时的操作,而如果利用程序来遍历这个文件夹,其结果就是将要耗费数秒钟或者更长的时间,并且同步操作会导致界面在搜索完毕后才出来,这样用户就不得不等待几秒钟甚至是数十秒钟,这种体验是相当不友好的。
那么如何解决这种方式呢?
其实,利用委托方式结合其BeginInvoke和EndInvoke方法,可以先显示出界面,然后再加载搜索结果,这样一来,就大大提高了用户体验,具体方式如下:
在程序中,我需要将搜索到的代码文件加载到ListView控件中显示出来,这样就需要有一个函数来添加ListViewItem,代码文件如下:
////// filter the filename from some files and attach them to ListView control /// /// public void LoadFileIntoForm(ListfileList) { List myFiles = fileList; AddListViewCrossThreads(null,deleteFlag); // remove all the items for (int i = 0; i < myFiles.Count; i++) { FileInfo file = myFiles[i]; ListViewItem lvi = new ListViewItem(); lvi.Text = GetFileName.GetFileName(file.FullName); lvi.Tag = file.FullName; // store the fullname AddListViewCrossThreads(lvi,addFlag); } } 
而我们读取那个耗时的代码文件的函数如下:
////// this function is the target to make async. /// because it takes a long time to load. /// ///public List LoadFileInfoAsync() { return LoadFiles.LoadFileByName(); } 
需要注意的是,这个LoadFileInfoAsync函数需要耗费数秒甚至是数十秒来搜索文件,其具体实现如下:
public ListLoadFileByName() { string keyWords = "scyGroupBox"; // file name contains words string searchPath = @"C:\Program Files\"; // file path DirectoryInfo directory = new DirectoryInfo(searchPath); var result = from p in directory.GetFiles("*.cs",SearchOption.AllDirectories).ToList() where p.Name.Contains(keyWords) select p; List files = result.ToList(); // transfer filenames into list collection return files; // return the result } 
其中SearchOption.AllDirectories表明搜索父文件夹下的子文件夹。
如何对LoadFileByName函数实现异步操作呢?
这个需要定义个委托,用委托来对这个函数进行异步操作:
////// this is the Begin Invoke method /// public void InvokeListView() { //delegate the funtion that perform long running operation AddListViewDelegate asyncAdd = new AddListViewDelegate(LoadFileInfoAsync); //start to load the funtion asynchorous., GetFileInfoResult is the end process IAsyncResult iar = asyncAdd.BeginInvoke(new AsyncCallback(GetFileInfoResult), asyncAdd); //perform loading notification AddListViewCrossThreads(AddNotification(),addFlag); }
利用Delegate的BeginInvoke可以实现异步操作,在异步操作的过程中,我们可以向用户显示提示信息,比如说“正在加载,请稍等….”,这样能达到一种比较好的用户体验,至于这种提示信息,我们在函数AddNotification中实现:
////// add the loading notification /// ///public ListViewItem AddNotification() { ListViewItem lvi = new ListViewItem(); lvi.Text = "Loading now, please wait..."; lvi.Tag = 1; return lvi; } 
但是现在遇到一个比较严重的问题,由于采用了异步,导致线程和界面发生了交互,这样就会产生exception,怎么解决呢,当然是利用Invoke方式来判断当前界面控件是否需要线程交互,如果需要,则利用委托方式来进行调用:
////// used to avoid the cross threads exception /// ///listview item ///0:add 1:delete public void AddListViewCrossThreads(ListViewItem lvi,int action) { if (lsvName.InvokeRequired) { AddListViewCrossThreadDelegate addlistviewdelegate = new AddListViewCrossThreadDelegate(AddListViewCrossThreads); lsvName.Invoke(addlistviewdelegate, lvi,action); } else { if (addFlag == action) { this.lsvName.Items.Add(lvi); } else if (deleteFlag == action) { this.lsvName.Items.Clear(); } } }
这样当异步进行完毕,我们就可以还原异步对象为当前代理对象,然后获取返回值了。
////// Invoke Async Complete /// /// public void GetFileInfoResult(IAsyncResult iar) { AddListViewDelegate asyncAdd = (AddListViewDelegate)iar.AsyncState; // get the operation object Listlist = asyncAdd.EndInvoke(iar); // get the async result LoadFileIntoForm(list); // add the ListViewItem result to ListView control } 
-----------------------------------------------------华丽的分割线--------------------------------------------------------
下面来说语法高亮,这个主要是采用了正则表达式,由于我写的不太完整,还请见谅,下面是主要代码,需要注意的是,在代码着色过程中,需要涉及到懒惰匹配法,意思就是最小匹配。需要用到(?i)来实现:
    public static void RichTextBoxEx(this RichTextBox richTextBox,string input)         {             richTextBox.Text = input;             input = input.Replace("\r\n","~");  //注意,\r\n会被认为是4字节,其实他只是一个字节,所以替换为一个字符来表示             //匹配关键字             string regexGrammer = @"using|namespace|                                      public|partial|                                     class|private|protected|                                     if|else|                                     int|string|double|                                     return|override|void|this|null|virtual";             MatchCollection mc = GetMatchedValue(regexGrammer, input);             foreach (Match match in mc)             {                 int length = match.Length;                 int index = match.Index;                 richTextBox.Select(index, length);                 richTextBox.SelectionColor = Color.Blue;             }             //匹配对象             string classGrammer = @"color|GraphicsPath|rectangle|Graphics|pen|LinearGradientBrush";             MatchCollection classMc = GetMatchedValue(classGrammer,input);             foreach (Match match in classMc)             {                 int length = match.Length;                 int index = match.Index;                 richTextBox.Select(index, length);                 richTextBox.SelectionColor = Color.FromArgb(43,145,175);             }             //匹配注释符号-->//这里使用了懒惰匹配(?i)             string commentGrammer = @"(?i)\//.*?~";             MatchCollection commentMC = GetMatchedValue(commentGrammer,input);             foreach (Match match in commentMC)             {                 int length = match.Length;                 int index = match.Index;                 richTextBox.Select(index, length);                 richTextBox.SelectionColor = Color.Green;             }             //匹配#号             string regionGrammer = @"(?i)\#.*?~";             MatchCollection regionMC = GetMatchedValue(regionGrammer, input);             foreach (Match match in regionMC)             {                 int length = match.Length;                 int index = match.Index;                 richTextBox.Select(index, length);                 Font f = new Font(new Font("宋体",12), FontStyle.Bold);                 richTextBox.SelectionFont = f;             }                         //匹配数字             string digitGrammer = "[0-9]";             MatchCollection digitMC = GetMatchedValue(digitGrammer, input);             foreach (Match match in digitMC)             {                 int length = match.Length;                 int index = match.Index;                 richTextBox.Select(index, length);                 richTextBox.SelectionColor = Color.Red;             }         }         private static MatchCollection GetMatchedValue(string grammer,string input)         {             Regex digitRegex = new Regex(grammer, RegexOptions.IgnoreCase | RegexOptions.Singleline);             MatchCollection matchCollection = digitRegex.Matches(input);             return matchCollection;         }  好了,介绍到这里,基本上就完了,附上效果图:
转载地址:http://eflvz.baihongyu.com/