拼吾爱程序人生

首页 » .Net编程 » Visual Studio.NET » .Net中的异步编程模式 (APM) (三)
cobra - 2008-10-3 15:41:00
如何实现支持APM的设备操作

前一篇中我们看到通过使用PowerThreading中的AsyncResult<T>类,我们可以很方便的将一个同步操作封装成异步的方式。同时使用这种方法和PInvoke,我们也可以为现有的C++设备库,如蓝牙设备提供一个.Net的异步类库。这样我们可以实现大部分对设备访问的.Net异步类库。

但当我们有特殊要求时,如果调整LCD亮度时,就需要调用Window API中的DeviceIoControl函数。PInvoke加上使用IO完成端口是件繁琐且容易出错的事情,幸运地是,我们有Richard,通过使用PowerThreading中的DeviceIO类,我们可以很方便的实现一个异步设备操作类。下面通过实现一个简单的异步打开光驱的方法,来看看如何使用Wintellect.IO.DeviceIO。

获得光驱句柄 在Win32中要访问一个设备,首先我们要调用CreateFile方法来获得该设备的文件句柄。PowerTheading中DeviceIO类对CreateFile进行了封装。我们可以容易通过创建一个DeviceIO对象来代表光驱。如下例:


Code




DeviceIO有两个构造函数,主要区别在于第一个参数。我们可以传入文件路径,或者传入一个已获得的文件句柄。如果文件路径不对,或者访问方式不对,会抛出Win32Exception的异常。DeviceIO实现了IDisposable接口,当不需要使用时可以调用Dispose方法来释放文件句柄。CDDrive也实现了IDisposable接口,及Finalizer以确保光驱的句柄能够释放。

设备操作控制码 在Win32中,如果我们要向IO设备发出指令,需要调用DeviceIoControl方法。该方法需要设备文件句柄,操作控制码,传入数据及返回数据的Buffer。文件句柄在前面已经获得,而这个操作控制码在Win32中,是一个DWORD类型,代表了不同的操作,如打开光驱,调亮LCD等等。
PowerThreading库中的DeviceControlCode 类可以帮助我们创建一个托管的结构。如弹出光驱的操作控制码IOCTL_STORAGE_EJECT_MEDIA定义如下:


Code




操作控制码分为4个部分:设备类型,操作,设备方法及访问方式。这个与WinSDK中Winioctl.h中定义相同,我们可以根据这个头文件很容易的创建对应的DeviceControlCode结构。下面是IOCTL_STORAGE_EJECT_MEDIA在头文件中的定义:


Code



在上面的IoControlCode静态类中,定义了4个操作控制码。这是因为如果我们弹出光驱或Eject可移动媒体,我们不能简单发出IOCTL_STORAGE_EJECT_MEDIA操作控制码,首先我们得发出FSCTL_LOCK_VOLUME锁住光驱以防止其他人写入,在发出FSCTL_DISMOUNT_VOLUME卸载卷,在发出IOCTL_STORAGE_MEDIA_REMOVAL移除媒体,最后才发出IOCTL_STORAGE_EJECT_MEDIA弹出光驱。具体可参考Microsoft KB 165721
发出设备操作 在第一步中,通过创建DeviceIO对象,我们已经获得了光驱的文件句柄。DeviceIO类提供了同步和异步的两套3个方法,来帮助我们发送操作到设备。同步方法内部实际调用的异步方法,所以下面我们看看3个异步方法:


Code



如果操作不需要返回数据时,可以使用BeginControl;如有返回数据可调用BeginGetObject,TResult对应返回数据的类型;而当返回的数据是数组是可使用BeginGetArray,TElement是返回数组的元素类型。我们可以在http://pinvoke.net/ 网站或google上查找TResult和TElement对应的托管类型定义。下面是弹出光驱的代码:


Code



上面的代码中,我们只使用了Control方法,其中IOCTL_STORAGE_MEDIA_REMOVAL需要传入数据。GetObject和GetArray的使用方法类似。
由于我们得循环的检查Lock是否成功,我们不得不使用线程池中的线程顺序的发出操作指令,因而该线程并没有最优化。如果我们都采取异步方式,我们不得不写很多回调或匿名函数,代码将变得很难看。这也是APM代码很麻烦的一个原因。后面的文章我们在来看看有没有更好的办法。

参考: Asynchronous Device Operations by Jeffery Richard
KB165721: How To Ejecting Removable Media in Windows NT/Windows 2000/Windows XP by Microsoft




(文/Nullnoid  出处/博客园)

 您可能对 [Visual Studio.NET] 的这些文章也感兴趣:

如何用Visual Basic编写病毒
DLR宿主规格说明书的草案已经发布
XNA Primitives画线 2(3D空间)
.net2.0 控件 winform Datagridview简介
.NET开发最新参考资料推荐_20081002
.NET组件和COM组件之间的相互操作
Mono 1.2发布及对Miguel de Icaza的采访
在 GridView 中增加记录的方法
深入探讨.NET中的钩子技术
.NET框架图解之一:Net基础,编译与执行引擎(下)
1
查看完整版本: .Net中的异步编程模式 (APM) (三)
Modify by pin5i DZNT_ExpandPackage 2.1.3258 2007-2008 pin5i.com
  Total Unique Visitors: