最近在写一款基于C#的网站备份文件扫描器,第一次写C#程序,其中遇到各种问题。在这里荟萃一下,给其他朋友一些帮助。
先秀一下效果:
问题一、多线程中修改UI抛出异常
一般异常信息是“现场间操作无效”、“调用线程无法访问此对象,因为另一个线程拥有该对象”。唉,线程它找不到对象,就跟我情人节没有对象,在这里写程序一个道理……苦逼。
我们需要使用“委托”的方式,委托UI线程来处理操作UI的那个函数。比如我们要写一个扫描器,界面上有一个进度条显示扫描的进度,没扫描一个URL我们需要给进度条增加一。这个时候“增加”这部分代码就需要写在单独的一个方法中,然后由工作线程委托UI线程来执行这个方法。
简要代码如下:
//线程中 void threadfunc(){ ... this.Dispatcher.Invoke(DispatcherPriority.Background, new probarDelegate(probarAdd)); ... } //声明一个委托 public delegate void probarDelegate(); //需要委托执行的函数 void probarAdd(){ probar.Value++; }这样就能和谐地让进度条滚动起来。
问题二、如何在WPF窗体中为listbox增加右键菜单
这个似乎很简单。在listbox的属性中,有一项叫“ContextMenu”,我们添加它,即可为listbox增加一个右键菜单。
但如何向菜单中增加项目?这个ContextMenu中有一项是Items,菜单项目理应在其中增加。但点击开了以后居然发现,增加按钮是灰色的!!
那我是怎么加进去两个项目的?既然图形化界面解决不了问题,只能手动修改xaml文件了。
找到窗口的xaml文件,其中有一个ContextMenu节点,我们把项目加入其中即可:
<ListBox Height="182" HorizontalAlignment="Left" Margin="6,47,0,0" Name="succBox" VerticalAlignment="Top" Width="346"> <ListBox.ContextMenu> <ContextMenu DataContext="{Binding ElementName=succBox}" Name="menuPop"> <MenuItem Header="复制" Click="Copy_Click" Name="copy_menu"></MenuItem> <MenuItem Header="导出" Click="Dump_Click" Name="dump_menu"></MenuItem> </ContextMenu> </ListBox.ContextMenu> </ListBox>
问题三、对话框怎么在任务栏上有自己的bar?
什么意思,比如我程序中要弹出一个对话框,让用户输入信息。弹出对话框(不管是模态还是非模态)后,居然会在任务栏上有自己的一项:
而以前写MFC程序默认不是这样的,而且各种程序按道理来说也不该这样。
于是探究了一番,发现原来只用在弹出的对话框属性中的ShowInTaskBar设置为false即可。
问题四、扫描经常扫到中间就停下了,或变得很慢
这个问题是大BOSS,研究了很久。后来在这里找到了答案:http://www.crifan.com/fixed_problem_sometime_httpwebrequest_getresponse_timeout/comment-page-1/
原来是程序限制了最大连接数,当有很多http连接没有关闭掉的时候,连接数达到了最大连接限制,就不能新增连接了。而之前的连接又没释放掉,造成了扫描停止。
解决方法在上面那篇文章中写的很详细,把System.Net.ServicePointManager.DefaultConnectionLimit设置更大,然后每次连接结束后close一下,不必要的情况下设置HTTP的KeepAlive=false。
感谢作者的分享。
程序不外放,有兴趣的基友单独找我要~