软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|Java 运行时监控
您现在的位置: 天极网 > 开发频道 > 为Windows应用创建简单的异步调用模式
全文

为Windows应用创建简单的异步调用模式

2005-10-18 11:14作者:出处:msdn责任编辑:方舟
天极软件专题专区精选     到天极软件“读编交流区”畅所欲言
Google专区 POPO专区 QQ专区 QQ挂机 了解Web2.0
Flash MX 视频教程 Photoshop视频教程 网页设计视频教程 照片处理数字暗房
PPT动画演示教程 Excel动画教程集 Word动画演示教程 Windows Vista专区
特洛伊木马专区 黑客知识教程专区 防火墙应用专区 注册表应用专区
Windows API开发专区 网络编程专区 VB数据库编程专区 图像处理与多媒体编程

  简介

  最近我编写了很多智能客户端应用,总结了一些能够使应用程序在后台调用Web Service时不冻结前台界面的异步调用方法。虽然当前.NET Framework本身已经提供了异步调用的机制,但我发现在Windows应用中这一机制比较难于把握,因为这时你需要正确的控制用户界面线程处理。

  在这篇文章中,我将教给您一种在Windows应用程序中实现异步调用Web服务的简单方法,通过这一方法,您不用再考虑后台线程与前台界面线程的交互关系了。

  服务代理

  Visual Studio.NET会生成较好的Web服务代理类,通过它可以异步的使用Web服务,但是这个代理类实现的是.NET Framework本身的异步调用机制,如上所述,这一机制对于Windows应用来说并不十分方便。由于这个原因,我一般不直接使用生成的代理类,而是在中间增加服务代理类。

  服务代理类就是增加了额外功能的类,这些功能可以帮助客户端程序与Web服务进行交互。服务代理类实现了许多有用的功能,包括数据缓存,安全身份管理,离线操作支持等等。本文中创建的服务代理类比.NET Framework本身的普通代理类实现了更简便的异步调用模式。

  用户界面线程

  应用程序从一个创建和管理用户界面的线程起始,这一线程被称为用户界面线程。大多数开发者本能的会使用用户界面线程完成所有的工作,包括进行Web服务调用,远程对象调用,访问数据库等等,大多数使用和性能方面的问题是由这一不恰当的方法引起的。

  问题的本质是你永远不可能精确的预知访问Web服务,远程对象,或者数据库所需的时间。而且当你在用户界面线程中进行这类的调用时,用户界面就有可能会产生令人恼怒的冻结。

  自然而然的,你会把这一类的调用放置在一个单独的线程中,但我更进了一步,建议您把所有的非用户界面工作坊制在一个分离的线程中。我的观点是,用户界面线程只用来管理用户界面,而所有那些你不能保证良好响应时间的对象调用都应该是异步的,无论是进程内的,跨进程的,还是跨计算机的。 无论如何,尽量使用户界面线程处理的异步调用模式简单化,我已经实现了一个与Visual Studio 2005里某个特性类似的简单异步调用模式。作为开始,我们首先解释一下当前.NET Framework中异步调用模式的工作原理。

  .NET异步调用模式

  系统生成的Web服务代理类的每个Web函数都有一个Begin和一个End方法,每个支持.NET Framework异步调用模式的对象都和这个类似。开始进行异步调用时,客户端调用Begin方法时就立即响应,或者在建立了访问Web服务的独立线程后马上响应。在这之后的某个时间,当Web服务访问完成后,客户端再调用End方法。

  但客户端如何知道什么时候调用End方法呢?Begin方法会返回一个IAsyncResult对象,可以帮助你跟踪异步调用的过程,也可以明确的等待后台线程完成,但如果在用户界面线程中进行这些工作,会降低整个系统的同步性。更好的方法是,在用户界面进程中注册一个回调函数,当其它工作完成时产生一个自动通知。

让我们看一段样例代码,在这段代码中,我们从一个Web服务中获取一些客户数据,这些功能通过Web服务代理类里的GetCustomerData方法完成。我们可以启动这个Web服务调用,并且用以下代码注册一个回调函数,用来在用户界面线程中产生与应用程序进行交互的功能。

private void SomeUIEvent( object sender, EventArgs e )
{
 // Create a callback delegate so we will
 // be notified when the call has completed.
 AsyncCallback callBack = new
 AsyncCallback( CustomerDataCallback );

 // Start retrieving the customer data.
 _proxy.BeginGetCustomerData( "Joe Bloggs", callBack, null );
}

  Web服务调用最终返回CustomerDataCallback方法,在这个方法中,我们需要调用真正用于获取客户数据的Web服务代理类中的End方法,这个方法可以实现如下:

public void CustomerDataCallback( IAsyncResult ar )
{
 // Retrieve the customer data.
 _customerData = _proxy.EndGetCustomerData( ar );
}

  现在,你必须注意,这一方法是被后台工作线程调用的。如果想在前台界面上使用刚刚获得的信息(例如在一个data grid控件中显示那些客户数据),一定不要忘记在用户界面线程中进行更新。如果忘了这样做,就会发生很多莫名其妙的错误,而且调试起来还相当的不易。

  那么我们怎么切换线程呢?我们可以使用服务代理的方法,所有的控件都源自这些对象的实现。我们可以实现一个从用户界面线程调用的方法,在这个方法内我们可以安全的更新我们的界面。使用Control.Invoke方法,我们必须给用户更新方法传递一个委托,现在,CustomerDataCallback方法的代码更新如下:

public void CustomerDataCallback( IAsyncResult ar )
{
 // Retrieve the customer data.
 _customerData = _proxy.EndGetCustomerData( ar );

 // Create an EventHandler delegate.
 EventHandler updateUI = new EventHandler( UpdateUI );

 // Invoke the delegate on the UI thread.
 this.Invoke( updateUI, new object[] { null, null } );
}

  UpdateUI方法可以按如下办法实现:

private void UpdateUI( object sender, EventArgs e )
{
 // Update the user interface.
 _dataGrid.DataSource = _customerData;
}

  这并不是十分非常严谨科学,因此可以使这一“两次跳转”的复杂问题简单化起来。关键在于异步方法的原始调用(以WinForm类为例)用来负责转换线程,并且需要另一个委托以及Control.Invoke方法。

共2页。 1 2 下一页 末页
相关搜索:
关注此文读者还看过
热门关注
特别推荐
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 Powered by 天极内容管理平台CMS4i
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众