开发经验

VS2015

  • git不支持ssh协议
  • 遇到编译报错的问题,有的时候重启下vs也许就能解决

Windows:

  1. 程序的安装路径是只读的权限,则会导致程序内部出现各种无法找到、空引用之类的错误。

Nignx

  1. localhost与127.0.0.1的区别在于,127.0.0.1是明确指定IPv4的回环地址,而localhost优先被翻译成IPv6回环地址[::1]

IIS

  1. 如果IIS部署好网页提示WebConfig Framework版本不对,看看应用程序的.net版本是不是设置得不对
  2. 如果IIS部署好网页提示找不到ASP的dll引用,看看是不是默认的ASP版本是其他版本,这个时候需要到对应framework路径下使用工具注册其asp版本为当前版本。
C:\
cd Windows\Microsoft.NET\Framework\V4.0.30319
aspnet_regiis.exe -iru

JavaScript

  1. 代码中的反斜杠需要用反斜杠转移,如需要输入'' 则需要coding '\'代替。(正则表达式中需要注意)
  2. 变量默认值为"default"字符串,而不是null,0等值
  3. alert 提示框,confirm确认框,prompt对话框(可弹出表单)

Mysql

  1. mysql无法连接应查看防火墙是否关闭,或者将mysql加入到防火墙信任列表中

Emgu.cv

  1. Error System.TypeInitializationException: The type initializer for 'Emgu.CV.CvInvoke' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'cvextern': 找不到指定的模块。 (Exception from HRESULT: 0x8007007E)
    这个错误需要将程序路径下的x86或者x64文件夹中的dll拷贝到程序路径下

摄像头

  1. 摄像头不能旋转,旋转会导致延迟,卡顿和花屏
  2. UDP连接rtsp不能跨网段,TCP连接rtsp可以跨网段
  3. 海康摄像头改了大多配置不会重启,即时生效,与其他相机重启不同,会导致一些问题。如:视频设置

解决问题

  1. 从现场分析最直接的原因,依个排除,而不是盲目的找啊找
  2. 上午联系人,下午做事情

WPF

  1. 界面操作在所属方法执行完毕后生效,如需即时生效,调用LayoutUpdate方法即可。
  2. 在添加控件后,所属方法执行完毕后才能获取到实际的宽高
  3. 在使用文件路径new bitmapimage比读取文件二进制转换成bitmapiage快得多
  4. 想要窗口在另一个窗口上,将其owener设置成那个窗口就可以了
  5. wpf里面的textbox的内容改变事件会受到某些输入法(如搜狗)的影响,改变内容与输入内容不一致。
  6. 界面动画比显示图片还耗费资源
  7. 尽量减少界面资源的反复创建,应采用资源池来进行维护。性能稳定且不易卡顿和产生内存泄漏。
  8. 窗口的AllowsTransparency 参数设置成True会导致程序在最小化到展开的切换动画中渲染时出现红色白竖条
  9. TextBox keydown不能捕捉back space和Enter,但是KeyUp能
  10. 播放gif不能使用MediaElement,它不能使用程序集的资源,只能使用相对路径的文件,在有的设备上无法寻址到gif图像,导致播放无画面,使用三方库WpfAnimatedGif解决。
  11. 用户自定义控件时,提示UserControl不支持直接内容,需要添加System.xaml的引用即可
  12. textbox中文输入法崩溃的问题解决——在控件上屏蔽输入法,代码如下:
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore" />

  1. Label不能直接显示下划线‘’,需要两个下划线在‘_’转义后才能显示
  2. DataGrid中添加DataGridCheckBoxColumn的列时,需要点两下才能选中,这是一个一直存在的bug。使用自定义模版添加一个checkbox则不会存在这个问题。
  3. Combobox 在selectindex与selectitem绑定没有在itemsource列表内的对象时,会往回触发一次为null的赋值,出现两次调用,第二次为null的BUG,这时只需要保存上一次的对象,判断空值时再设置一次即可解决。
  4. checkbox的显示效果在鼠标按下触发, 但是值计算(按照当时的ischecked取反)在鼠标松开后触发。如果其他事件或线程在这期间修改了checkbox的ischecked的值,则会导致鼠标松开始值计算出现问题,从而引发选中失效的问题。
  5. checkbox的选中改变事件是click,其选中值触发也是与click周期一致。
  6. toolkit splitbutton 的IsEnabled属性在绑定时需要注意,只有使用Mode=OneWay才能使得绑定属性生效时,其状态改变,否则不生效。
  7. Converter内部由于传入错误的类型与代码产生异常后,会导致界面属性绑定关系失效(可能是局部,也可能使全局的,命令一般不失效),从而使得设置property属性后界面不更新。
  8. 绑定时,枚举类型默认为第一个枚举值。
  9. 当grid设置多行,且行高为固定数字,其中一行设置了minheight时,使用gridsplitter拖动使得设置minheight那行缩小,这样会导致另一个被影响的行高度无限增加。通过都使用 6* 这样的星号表示行高可以解决这个问题。
  10. Combobox在编辑状态下修改了一个项的显示名称后,回到普通状态,绑定关系依旧在,但选中会被置为空。
  11. 在使用WindowsChrome拓展类时需要注意,MSDN中所属的命名控件System.Windows.Shell(Assembly PresentationFramework)是存在,但是与描述不一致。因为MSDN是描述的4.5 版本,但是在.net 4.5中仍然提供的是PresentationFramework的4.0 版本(尼玛,微软没更新)。解决方法是采用三方库WPFToolkit,其中提供了WindowsChrome的实现。
  12. 当在xaml中使用X:static 访问Resources.resx中的资源出现错误时(null,无法转换),修改Resources.resx的访问修饰为Public即可实现访问
  13. 滚轮一共有24个凹槽,滚动一个凹槽改变+-120
  14. 双向绑定想要在用户修改界面时触发某些操作,需要绑定SourceUpdated事件,注意不是TargetUpdated事件,并打开NotifyOnSourceUpdated的开关。不要问为什么,我特么也很纳闷为什么绑定目标改变是SourceUpdated事件被触发
  15. 控件绑定IsEnabled后,在你更换他的DataContext后有的不会生效,是因为部分控件需要设置Mode="TwoWay",不要问为什么,我特么也是懵逼的
  16. 不管对一个还是多个控件进行IsEnabled的绑定和Vissibility的绑定时,最好采用一个容器将他们包起来,绑定容器的IsEnabled或者Vissibility。
  17. 调整windows的文本缩放大小会改变系统的DPI,会导致winform的尺寸计算出现问题(wpf不会),原因是wpf的宽高都是渲染大小,而winform则是实际的像素大小。例:在使用wpf的宽高计算winform控件尺寸宽的时候需要进行 wpfWidth * 当前DPI / 96 的运算。当你的界面遇到客户分辨率是对的,显卡驱动装了的,但是就是显示有问题的情况,请检查文本缩放大小的设置。
  18. 在控件模版中使用TemplateBinding时,注意它较binding缺少类型转换,使用的时候要求类型必须一致。如果类型不一致则使用Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value}" 这样的代码来绑定
  19. 编写依赖属性时需要注意,如果需要传输的是数据,而数据是连续的值类型流,最好使用一个类将其包裹起来,不然值类型相同的话则不会触发依赖属性改变
  20. 编写依赖属性时需要注意,如果需要传输的是数据,而数据是连续的值类型流,最好控制更新速度,如果同时多次更新,wpf只触发一次改变
  21. wpf绑定不适用于流数据,频繁更新数据必须使用方法调用,不然会出现数据延迟+数据丢失
  22. tabitem 有一个bug ,当banding tabitem的Vissibility,tabitem标签隐藏了,但是content不会隐藏。如果把content的Vissibility也绑定就会一起隐藏,但是如果隐藏的是第一个标签,则不会自动选择第二个显示的标签。这个时候需要将Vissibility的属性绑定到IsSelected来控制隐藏后的选择变化。
  23. textbox,combobox 在设置背景字体颜色后,被显示与隐式(父容器被)禁用后,背景颜色被设置为默认禁用颜色。可以通过重写textbox 的控件模版让ScrollViewer的背景颜色与控件背景一致
  24. wpf在资源字典添加资源时需要注意有先后顺序,被引用的先定义。当引用多个资源字典时,需要将在其他字典中被引用的放在前面。当两个资源字典在另一个字典中被一起引用时,IDE编辑时可以互相使用资源,但编译通不过。如果没满足这几点,运行时就会出现无法定位的错误,常见的如:DependencyProperty.UnsetValue。
  25. 自定义可以点击操作的控件模版时,经常会出现元素间的存在间隙的情况。这种情况不能使用margin来达到效果,因为间隙不能响应点击操作。可以通过添加一个背景透明的Grid来填充空白,空白处也能响应了。
  26. 当在控件的DataTemplate中加入label控件时,如果改写控件的样式,那么样式的foreground作用不到label上去,需要采用TextBlock才行。
  27. 在warppannel或者stackpanel中使用了没有指定宽高让其自适应的包含图片的控件,容易导致后续的边框控件(rectangle,border,grid等)渲染出1px的误差,且色值不一致
  28. 切图边缘如果未对齐像素栅格,界面显示时未对齐的像素将显示半透明的颜色,导致图的边缘出现模糊的边影响视觉效果
  29. TabControl中如果隐藏可第一个tabitem,选中第二个tabitem时,焦点会被转移到content内的第一个输入框上,真乃神之BUG,只需要在第一位放一个宽度为0的输入框即可解决。
  30. 想要给控件的style里添加DataTrigger绑定属性来触发样式的改变,则被setter的属性不要在控件上直接定义对应值,而是在style内setter初始值,不然不会被触发
  31. System.Windows.Shell和Microsoft.Windows.Shell 在.net4.5中都放到了PresentationFramework中,如果需要使用只需要引用Presentation就可以了,在xaml中也是一样不过是网址形式的。
  32. WPF的xaml中出现错误提示存在的命名空间中的类提示不能再命名空间中找到类型,则说明你只是再当前的Debug或Release版本生成了,需要切换到另一个版本再生成一次,切回来就好了。它让我明白雨露均沾这个道理,不然就总有一方要给你制造麻烦。
  33. 当使用其他库,产生引用版本冲突时,如下,标记新旧版本,默认其他库使用高版本依赖。

  
    
      
      
    
  

  1. 当使用App后台代码,比如重写OnStartup方法,却启动不被调用。这个时候需要你查看一下是否在App.xaml中使用了StartUri,或者命名空间与Xaml中是否一致
  2. 当程序进入中断状态,因为一些框架和系统等得报错而毫无明显的问题提示时。这个时候可以点击中断页面上的诊断工具,查看其中的“事件”可能会帮助你解决问题。
  3. 在Style中想要设定子类型控件的样式,设置其style属性会报错,解决方法是使用BaseOn继承指定的style即可。
  4. 如果你使用列表绑定时出现 Unable to cast object of type 'MS.Internal.NamedObject' to type 'NameSpace.Class' 那么升级.net版本到4.5以上吧,这是一个.net 4.0的绑定BUG,它会导致绑定断开
  5. 如果自定义 DependencyProperty 需要默认为双向绑定(不指定为单向),需需要在注册属性时使用FrameworkPropertyMetadata 而不是PropertyMetadata。代码如下:
public static readonly DependencyProperty CunstomProperty = DependencyProperty.Register("Cunstom", typeof(string), typeof(CustomControl),
            new FrameworkPropertyMetadata(null,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
  1. 需要注意,Template 中的TemplateBinding是以下代码的简化形式:
{Binding RelativeSource={RelativeSource TemplatedParent},Path=XXX,Mode=OneWay}

可以看见默认为单项绑定,当需要双向绑定属性时,则需要将TemplateBinding 改写为:

{Binding RelativeSource={RelativeSource TemplatedParent},Path=XXX,Mode=TwoWay}
  1. 自定义控件依赖属性(DependencyProperty)的初始值最好在注册方法内指定,这样比在构造函数中指定的好处是——免于在某些场景下构造函数后于设定的值被调用,而这种情况就会导致构造函数中默认的值覆盖了在xaml标签的指定值,而运行效果与期望效果不一致。比如将控件在模板中使用时就会出现这种错误情况。
  2. 给RedioButton绑定事件到命令后,如果在标签上设置了IsEnabled="False"则会失效。因为IsEnabled是构造时设置,事件到命令绑定在之后,会触发命令是否可以执行检擦,将IsEnabled设置为True
  3. 在Style中Setter 子样式子模板时,经常StaticResource 不能引用到其他样式,这时候只要使用DynamicResource 即可
  4. 不能将界面控件、节点元素、节点列表(如:MenuItem)作为源绑定到多个目标上,因为一个节点只能有一个父节点
  5. TabControl绑定ItemSource后,由于模板的原因,切换选中Item时,Content的DOM结构没有发生改变,只是绑定的值发生变化。当某些需求要在面板上显示历史数据时,则需要每个Item对应一个Content,这个时候可以在TabControl的基础上自行编写Items的新增和切换逻辑。更通俗的用法是,使用ContentTemplate设置DataTemplate绑定Content,在viewmode中实现一个Control,切换时则会将Control作为绑定资源切换。

C#

  1. webclient下载不会超时,会盲等,文件不存在会卡住线程,且无法退出。
  2. 不要再异常的catch里面做耗时的操作
  3. 线程循环内部try{} catch()
  4. 在线程中调用非托管代码时,注意是否耗时,线程结束,非托管代码不会退出。
  5. 跨平台,跨语言 约定大于默认,同一平台,同一语言,默认大于约定
  6. 少写静态类,多些单例类
  7. Task.Run是委托clr线程池来做的,会影响其他的线程,特别是界面线程
  8. SpintWait.SpinUntil要比sleep对CPU消耗要更小,但是SpinUntil 停止时间在100ms内不准确,Sleep准一些。但是Sleep偶尔会很高,受CPU使用的的影响,应该是上下文切换耗时。Thread.SpinUntil不要使用,完全受CPU影响, 一点不准。但是无限空转时SpinUntil就很准,Sleep就不准了。
  9. 同一对象,尽量不在多个线程被操作
  10. datetime 没有stopwatch准确,在计算线程耗时的时候使用stopwatch才能精确到毫秒
  11. 多线程Queue不安全,出队列会返回null
  12. 退出打印日志
  13. 启动、退出各个模块,线程打印日志
  14. 多人协作,首先要定的就是接口。接口会影响到业务的逻辑,如果一开始没有定好接口,后面写好了再来改就涉及到两边的代码了。
  15. 获取windows屏幕,有两个概念,一个是工作区,是除任务栏之外的可用区域。一个是显示区,指整个系统显示的区域。
  16. 深层递归容易导致堆栈溢出
  17. UI线程被卡的时候,处于UI线程的dispatchertimer也会卡产生终端,当需要定时处理数据的时候,使用后台计时器是最好的选择。System.Timers.Timer
  18. 内存泄漏先看非托管,再看大对象,再看委托。循环匿名委托(闭包)会导致内存泄漏,闭包的对象不能被释放。
  19. 系统中传递引用数据和用列表对象存储引用对象时,需要注意引用的引用,应用移除机制是否可靠,引用是否被其他地方占用等情况,放置被引用的对象未释放导致内存增长
  20. 获取config文件的配置使用
    ConfigurationManager.AppSettings.Get() 方法
  21. 多个字符串分割的方法 line.Split(new string[] { "<,>" }, StringSplitOptions.None)
  22. 内存访问越界异常有可能是分配空间不足,跨线程访问,在托管线程中访问非托管线程的对象。
  23. 捕捉非托管代码抛出内存越界等异常时,添加HandleProcessCorruptedStateExceptions属性描述方法
  24. Assembly.GetExecutingAssembly();是获取当前程序集信息,如果当前程序集是一个类库就是类库的信息,而不是引用类库的主程序集信息。
  25. byte[] 拷贝 Buffer.BlockCopy是原生操作效率高,但也只支持原生byte[],Array.Copy性能较高 ,支持装箱拆箱的对象数据操作
  26. Obsolete 标记方法过时,但仍然可用,只是编译会报警告。如果不想方法被调用,首行添加 throw new NotImplementedException(); 保证。
  27. .net 高版本调用低版本时,release情况下可能会出现一些操作无法执行
  28. 除了byte[]数组,其他类型copy尽量不要使用buffer.blackcopy,会有长度问题,出现漏copy
  29. 使用xmlSerializer + XmlWriter 进行对象的xml文件保存时,需要xml文件进行换行缩进的代码如下:
XmlWriter writer = XmlWriter.Create(fileName, new XmlWriterSettings() { Indent = true });
  1. 枚举默认值是第一个,所以存在UnKown,None之类的枚举要写在第一个。
  2. process 需要设置EnableRaisingEvents 为true,Exited事件才有效。需要注意的是,在未触发Exited时,程序已经结束,调用HasExited属性也会触发检查,而触发Exited事件。
  3. 当使用 += ()=>{} 这样的匿名方法注册事件时,极易导致内存泄漏。1. 匿名方法无限注册,无法取消。2. 本该释放的对象被占用。
  4. 当进行精确值计算时,使用float与double乘除加减容易造成精度丢失,在多次计算或取舍之后就会出现误差。建议采用decimal进行计算,计算后转换成对应的float或者double类型。float转换为double就会丢失精度,需要先转换成decimal,再转成double
  5. 在几个类型进行混合运算时,一定要先运算相同类型再运算不同类型,减少类型频繁转换花费的时间
  6. c#中enum可以添加flag标记,而后就可以进行逻辑与或运算
  7. BUFFER.BlockCopy 有32k限制,如果你的数据字节数超出了32000,则将其copy32000之前,导致出现错误。所以在copy非byte类型时,尽量使用array.copy
  8. System.Timers.Timer, System.Threading.Timer, System.Threading.SpinWait, 的时间间隔都会大于设置的时间间隔几十毫秒不等。System.Threading.Sleep 的时间间隔比较准确,如果需要准确的时间间隔,使用Sleep。如果需要高性能,而无需太准的则使用Timers.Timer和SpinWait。注意Sleep不能过多的使用,不然上下文切换会导致CPU占用上升且花费时间。
  9. Buffer.BlockCopy可以实现byte[] 与其他类型数组的转换
  10. Task和Thread的区别,Thread完全由自己控制,Start后即刻启动,调度优先级也高。Task调度由调度器决定,Start后一般不会马上执行。
  11. string类型也是引用,但是赋值的时候却总是“克隆”而不是引用传递。
  12. 多线程之间通信,要在代码中添加委托传输数据,在另外的线程里来执行委托。神马你没哟写多线程?你的界面和你的其他代码就是不同的线程。一般就是先判断自己是不是主线程,是就执行,不是就添加委托。
  13. 对于事件的参数,如果要进行使用和改变,最好是先在类里克隆一个副本,这样可以降低引用导致的数据异常,访问异常等一系列一样。但是在多个线程执行可能同时访问到一个对象的时候,lock后操作对数据的完整性很重要,但是不能滥用,不然效率低下延迟很高。但也不能一味所有的都克隆,克隆也是很耗费时间的。
  14. 函数返回出口不要过多,不便于调试,可以声明一个返回值,每种情况下赋值,在最后统一返回。
  15. 能用枚举标识的状态就不用1‍,0,-1。枚举为了好运算,最好使用2^0 ,21,22……2^n,这样的数列。因为枚举的运算是二进制位运算,使用2的幂非常容易就能够得出结果。‍
  16. 方法参数在开始一定要判断空,判内容,判长度,判神马再使用。。。
  17. 需要保存历史记录用以和后来者比较神马的,可以直接用字典,因为字典有神奇的功能,不仅能tryget ‍‍,还能 containskey ,还能直接用ID作为索引进行赋值,而无需知道字典中有无这个值,因为有就覆盖,没有就添加。‍‍
  18. 调试方法有很多。界面用messagebox,类库用new exception(“xxxxxx”)。
  19. 注释。公有方法‍‍“///”,私有“//”,特别功能的代码块一定要注释,反正果断事件你自己就看不懂了,或者人家乍一看看不懂的地方都要加上你的注释。‍‍
  20. 写项目的时候一定要伴随这建立一个‍‍test项目,测试代码、数据库操作神马的弄进去整吧。‍‍
  21. 对于已知而不愿意写类型声明对象来接收方法返回值,实例化等对象操作时,可以使用‍‍var来代替特定类型。但是编译时就被替代成对应类型,非运行时动态解析。‍
  22. 事件非函数,一个是同步自己调用,一个是异步其他线程调用。决定了事件在线程之间通信必须要效率。所以事件是来传送“改变”而不是传值。在事件参数设计和代码逻辑设计上一定要注意这个影响性能和产生异步引用的东西。‍
  23. 在传递对象时,return是传递的对象的引用,所以在方法内,要返回的对象不要使用using 或dispose去回收它,不然外部使用返回值就会出错。
  24. 对象回收,系统句柄对象需要回收(如:GDI,DX,网络连接等),自建对象(类)不用回收。
  25. 线程锁,使用无安全检查的object对象来当做一个线程锁。锁住的是一个代码片段对于不同线程的可访问性。dictionary有安全检查,锁无用。
  26. 在主线程退出之前,先要结束其他线程,保证安全。

你可能感兴趣的:(开发经验)