Automate Everything

关于自动化相关的任何东西,包括自动化测试,Visual Studio宏, 自动化安装部署等

Archive for the ‘C#’ Category

.Net 内存泄露检查以及垃圾回收机制

星期三, 07月 16th, 2008

现在在做Memory Leak的测试,需要覆盖到Native的C++ Code和Managed C# Code,下边是学习笔记和一些自己的想法…

Native的C++代码来说,内存泄露就是New的对象没有delete,概念相对Managed来说要简单很多,而且很好理解,可以用Memory Validator来做,这个工具会很明显的给出什么地方可能会有内存泄露,并给出Call Stack,我们可以看到在哪个对象New了以后没有delete。我们通过在整个solution中搜索这个变量,去看对象有没有被Return、赋值或者delete,如果都没有的话,那说明这个地方是一个内存泄露。

对Managed的C#代码来说,内存泄露的概念就跟Native的C++概念不同。因为所有的New所分配的内存是在托管堆上分配的,所以不存在一般意义上的内存泄露。对Managed Code来说,内存泄露就是指一些没有用的对象被reference,导致GC不能回收,从而造成这部分内存相对泄露(这个是我自己的概念^_^)。我们可以通过.Net Memory Validator和.NET Memory Profiler 3.1来跟踪内存的使用情况,从而分析内存泄露。

两个例子:

1. 比如一个全局的ArrayList里边New了很多的对象,这个ArrayList只在一个函数里边使用,那么在这个函数调用结束的时候,就必须给ArrayList赋值为null。否则这个全集的ArrayList只能等到程序结束的时候才能被释放,在这个期间因为ArrayList的引用,导致ArrayList里边的对象不能被释放回收。

2. 比如一个SolidBrush对对象,没有包括在using语句中,那个这个对象就不会自动被调用despose接口,导致内存泄露。

把这篇文章分享到: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • bodytext
  • Google
  • Facebook
  • Furl

C#中使用多线程,并与UI同步

星期一, 04月 21st, 2008

我们有时候需要做一些很耗时间的操作,比如到网络上拿一些数据或者对很多数据进行运算处理,如果是在单线程的程序中,这些运算就会阻塞UI线程,现象就是UI不能响应用户的任何操作,不会刷新。这个时候用户很可能以为程序已经死掉,从而造成很差的用户体验。
解决方法:将很耗时间的运算和处理放在单独的一个线程中进行,UI操作不会受到影响,用户还可以进行其它操作(如果UI中有些操作依赖于当前的的处理,我们可以先将它灰掉,在处理线程结束后再使其可用。更好的是在UI的线程中放一个进度条,来告诉用户当前的处理进度)

在C#中做多线程的处理非常简单:
只需要用代理(Delegate)和跟代理相关的两个函数:
1. BeginInvoke  这个方法将代理指向的方法在一个单独的线程中调用
   使用方法:
     a. 声明一个代理的对象
     b. 用这个代理对象调用BeginInvoke方法         

2. Control.Invoke 这个方法在当前UI的线程空间内调用代理所指向的方法
    使用方法:
      a. 声明一个代理对象
      b. 调用控件的Invoke方法(一般在WinForm程序中,可以调用this.Invoke方法),将代理对象作为参数传递过去

看代码:

   1: private delegate void LoadPhotosDelegate(SearchParam param);
   2: private void LoadPhotosFromFlickr(SearchParam param)
   3: {
   4:     UpdateUIDelegate updateUI = new UpdateUIDelegate(this.UpdataUI);
   5:     this.Invoke(updateUI);
   6: }
   7:  
   8: private delegate void UpdateUIDelegate();
   9: private void UpdataUI()
  10: {
  11:     //进行UI的更新操作,比如更新进度条,显示图片等
  12: }
  13:  
  14: private void SearchPhoto(SearchParam param)
  15: {
  16:     LoadPhotosDelegate loadPhotos = new LoadPhotosDelegate(LoadPhotosFromFlickr);
  17:     loadPhotos.BeginInvoke(param, null, null);
  18: }

把这篇文章分享到: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • bodytext
  • Google
  • Facebook
  • Furl

在C#中调用API进行截屏

星期一, 04月 21st, 2008

看代码:

需要Reference下面的DLL:
  System.Drawing
  System.Windows.Forms
  WindowBase

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using System.Windows;
   5: using System.Windows.Forms;
   6: using System.Drawing;
   7: using System.Runtime.InteropServices;
   8:  
   9: namespace ConsoleApplication1
  10: {
  11:     class Program
  12:     {
  13:         [System.Runtime.InteropServices.DllImport("gdi32.dll")]
  14:         public static extern IntPtr CreateDC(string driver, string device, IntPtr res1, IntPtr res2);
  15:  
  16:         public enum TernaryRasterOperations
  17:         {
  18:             SRCCOPY = 0×00CC0020, /* dest = source*/
  19:             SRCPAINT = 0×00EE0086, /* dest = source OR dest*/
  20:             SRCAND = 0×008800C6, /* dest = source AND dest*/
  21:             SRCINVERT = 0×00660046, /* dest = source XOR dest*/
  22:             SRCERASE = 0×00440328, /* dest = source AND (NOT dest )*/
  23:             NOTSRCCOPY = 0×00330008, /* dest = (NOT source)*/
  24:             NOTSRCERASE = 0×001100A6, /* dest = (NOT src) AND (NOT dest) */
  25:             MERGECOPY = 0×00C000CA, /* dest = (source AND pattern)*/
  26:             MERGEPAINT = 0×00BB0226, /* dest = (NOT source) OR dest*/
  27:             PATCOPY = 0×00F00021, /* dest = pattern*/
  28:             PATPAINT = 0×00FB0A09, /* dest = DPSnoo*/
  29:             PATINVERT = 0×005A0049, /* dest = pattern XOR dest*/
  30:             DSTINVERT = 0×00550009, /* dest = (NOT dest)*/
  31:             BLACKNESS = 0×00000042, /* dest = BLACK*/
  32:             WHITENESS = 0×00FF0062, /* dest = WHITE*/
  33:         };
  34:  
  35:         [DllImport("gdi32.dll")]
  36:         public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth,
  37:             int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
  38:  
  39:         public static void CaptureDesktop(string sPath)
  40:         {
  41:             Rect rect = new Rect();
  42:             rect.Width = Screen.PrimaryScreen.Bounds.Width;
  43:             rect.Height = Screen.PrimaryScreen.Bounds.Height;
  44:  
  45:             IntPtr dcTmp = CreateDC("DISPLAY", "DISPLAY", (IntPtr)null, (IntPtr)null);
  46:             Graphics gScreen = Graphics.FromHdc(dcTmp);
  47:             Bitmap image = new Bitmap((int)(rect.Width), (int)(rect.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  48:             Graphics gImage = Graphics.FromImage(image);
  49:             IntPtr dcImage = gImage.GetHdc();
  50:             IntPtr dcScreen = gScreen.GetHdc();
  51:             BitBlt(dcImage, 0, 0, (int)(rect.Width), (int)(rect.Height), dcScreen, (int)(rect.Left), (int)(rect.Top), TernaryRasterOperations.SRCCOPY);
  52:             gScreen.ReleaseHdc(dcScreen);
  53:             gImage.ReleaseHdc(dcImage);
  54:  
  55:             image.Save(sPath);
  56:         }
  57:  
  58:         static void Main(string[] args)
  59:         {
  60:             CaptureDesktop("c:\\1.bmp");
  61:         }
  62:     }
  63: }

把这篇文章分享到: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • bodytext
  • Google
  • Facebook
  • Furl

在C#中如何模式鼠标键盘操作

星期五, 04月 11th, 2008

上一篇讲了在自动化测试中如果控件不能识别,我们最后的办法是模拟鼠标键盘,这一篇就讲如何来做。

首先我先讲在C#中怎么做,至于在C++或者脚本中怎么做,留在后边来讲

对C#来说,键盘的模拟比较简单,在.Net Framework中System.Windows.Forms.SendKeys这个类

鼠标呢,看下边代码:

   1: [DllImport(“user32″)]
   2: public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
   3: 
   4: [Flags]
   5: public enum MouseEventFlags
   6: {
   7:     Move = 0×0001,
   8:     LeftDown = 0×0002,
   9:     LeftUp = 0×0004,
  10:     RightDown = 0×0008,
  11:     RightUp = 0×0010,
  12:     MiddleDown = 0×0020,
  13:     MiddleUp = 0×0040,
  14:     Wheel = 0×0800,
  15:     Absolute = 0×8000
  16: }
  17: 
  18: void PixelsToAbsCoors(double x, double y, ref double xOut, ref double yOut)
  19: {
  20:     //points are based on current screen size setting   
  21:     xOut = x * 65536 / Screen.PrimaryScreen.Bounds.Width + 0.5;
  22:     yOut = y * 65536 / Screen.PrimaryScreen.Bounds.Height + 0.5;
  23: }
  24: public void Move(double x, double y)
  25: {
  26:     PixelsToAbsCoors(x, y, ref x, ref y);
  27:     mouse_event((int)(MouseEventFlags.Move | MouseEventFlags.Absolute), (int)x, (int)y, 0, 0);
  28: }
  29: public void Click(double x, double y)
  30: {
  31:     Move(x, y);
  32:     PixelsToAbsCoors(x, y, ref x, ref y);
  33:     mouse_event((int)(MouseEventFlags.LeftDown | MouseEventFlags.Absolute), (int)x, (int)y, 0, 0);
  34:     mouse_event((int)(MouseEventFlags.LeftUp | MouseEventFlags.Absolute), (int)x, (int)y, 0, 0);
  35: }
把这篇文章分享到: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • bodytext
  • Google
  • Facebook
  • Furl