·您的位置: 首页 » 资源教程 » 编程开发 » ASP.NET » ASP.NET创建XML Web服务全接触(10)

ASP.NET创建XML Web服务全接触(10)

类别: ASP.NET教程  评论数:0 总得分:0
异步Web服务(2)

    

  和XML Web服务异步地通讯

  和一个XML Web服务异步通讯遵循被Microsoft.NET Framework其它部分使用的异步设计模式。然而,在你取得那些细节之前,重要的是注意一个XML Web服务不必特意的写来处理用于异步调用的异步请求。你使用Wsdl.exe为你的客户端创建的代理类自动地创建用于异步调用XML Web服务方法的方法。即使只有一个XML Web服务方法的同步实现也是这样的。

  .NET Framework异步方法调用设计模式

  用于调用异步方法的设计模式,尤其是用于.NET Framework,针对每个同步方法分别有两个异步方法。对每个同步方法,都有一个Begin异步方法和一个End异步方法。Begin方法被客户端调用来开始方法调用。也就是说,客户端指示这个方法来开始处理方法调用,但是立即返回。End方法被客户端调用来取得XML Web服务方法调用执行的处理结果。

  一个客户端如何知道何时调用End方法?.NET Framework定义了两种方法来实现客户端判断其时间。第一种是传送一个回调函数到Begin方法,当方法已经完成处理的时候调用。第二个方法是使用WaitHandle类的一个方法来导致客户端等待方法完成。当一个客户端实现第二个方法,并且调用Begin方法,返回值不是XML Web服务方法指定的数据类型,而是一个实现IAsyncResult接口的类型。IAsyncResult接口包含一个WaitHandle类型的AsyncWaitHandle属性,实现支持等待同步对象变为带有WaitHandle.WaitOne、WaitAny和WaitAll标记的方法。当一个同步对象被标记的时候,它指示等待特定的资源的线程可以访问资源的。如果一个XML Web服务客户端使用wait方法仅仅异步地调用一个XML Web服务方法,那么它可以调用WaitOne来等待XML Web服务方法完成处理。

  重要的是注意不管客户端选择来与XML Web服务异步通讯的两种方法中的哪一种,SOAP消息发送和接收都与同步通信时吻合。也就是说,只有一个SOAP请求和SOAP响应通过网络发送和接收。代理类通过使用一个不同的线程而不是客户端用来调用Begin方法的线程来处理SOAP响应。因此,客户端可以继续执行线程上的其它的工作,而代理类处理接收和操作SOAP响应。

  实现一个产生异步的方法调用的XML Web服务客户端

  用于从使用ASP.NET创建的XML Web服务客户端产生一个到XML Web服务的异步调用的体系结构被嵌入.NET Framework和由Wsdl.exe构造的代理类中。用于异步调用的设计模式被.NET Framework定义,代理类提供和一个XML Web服务异步通信的机制。当一个用于XML Web服务的代理类被使用Wsdl.exe构造的时候,有三个方法分别被创建,用于XML Web服务中的公共XML Web服务方法。下面的表格描述那三个方法。

  代理类中的方法名 描述

  <NameOfWebServiceMethod> 同步发送用于名为<NameOfWebServiceMethod>的XML Web服务方法的消息。

  Begin<NameOfWebServiceMethod> 开始与名为<NameOfWebServiceMethod>的XML Web服务方法的异步消息通信。

  End<NameOfWebServiceMethod> 结束与名为<NameOfWebServiceMethod>的XML Web服务方法的异步消息通信,从XML Web服务方法中取得完成的消息。

  下面的代码示例是一个XML Web服务方法,它可能花费相对长的时间来完成处理。因此,当你应该设置你的XML Web服务客户端来异步地调用XML Web服务方法的时候,它是一个很好的示例。

[C#]
<%@ WebService Language=\"C#\" Class=\"PrimeFactorizer\" %>

using System;
using System.Collections;
using System.Web.Services;

class PrimeFactorizer {

 [WebMethod]
 public long[] Factorize(long factorizableNum){
  ArrayList outList = new ArrayList();
  long i = 0;
  int j;
  try{
   long Check = factorizableNum;

   //Go through every possible integer
   //factor between 2 and factorizableNum / 2.
   //Thus, for 21, check between 2 and 10.
   for (i = 2; i < (factorizableNum / 2); i++){
    while(Check % i == 0){
     outList.Add(i);
     Check = (Check/i);
    }
   }
   //Double-check to see how many prime factors have been added.
   //If none, add 1 and the number.
   j = outList.Count;
   if (j == 0) {
    outList.Add(1);
    outList.Add(factorizableNum);
   }
   j = outList.Count;

   //Return the results and
   //create an array to hold them.
   long[] primeFactor = new long[j];
   for (j = 0; j < outList.Count; j++){
    //Pass the values one by one, making sure
    //to convert them to type ulong.
    primeFactor[j] = Convert.ToInt64(outList[j]);
   }
   return primeFactor;
  }
  catch (Exception) {
   return null;
  }
 }
}

[Visual Basic]
<%@ WebService Class=\"PrimeFactorizer\" Language=\"VB\" %>
Imports System
Imports System.Collections
Imports System.Web.Services

Public Class PrimeFactorizer
<WebMethod> _
Public Function Factorize(factorizableNum As Long) As Long()
 Dim outList As New ArrayList()
 Dim i As Long = 0
 Dim j As Integer
 Try
  Dim Check As Long = factorizableNum

  \'Go through every possible integer
  \'factor between 2 and factorizableNum / 2.
  \'Thus, for 21, check between 2 and 10.
  For i = 2 To CLng(factorizableNum / 2) - 1
   While Check Mod i = 0
    outList.Add(i)
    Check = CLng(Check / i)
   End While
  Next i
  \'Double-check to see how many prime factors have been added.
  \'If none, add 1 and the number.
  j = outList.Count
  If j = 0 Then
   outList.Add(1)
   outList.Add(factorizableNum)
  End If
  j = outList.Count

  \'Return the results and
  \'create an array to hold them.
  Dim primeFactor(j - 1) As Long
  For j = 0 To outList.Count - 1
   \'Pass the values one by one, making sure
   \'to convert them to type ulong.
   primeFactor(j) = CLng(outList(j))
  Next j
  Return primeFactor
 Catch
  Return Nothing
 End Try
End Function
End Class


  下面的代码示例是一个Wsdl.exe生成的代理类的一部分,用于上述XML Web服务方法。注意BeginFactorize和EndFactorize方法,因为它们被用来与Factorize XML Web服务方法异步通信。

public class PrimeFactorizer : System.Web.Services.Protocols.SoapHttpClientProtocol {

 public long[] Factorize(long factorizableNum) {
  object[] results = this.Invoke(\"Factorize\", new object[] { factorizableNum});
   return ((long[])(results[0]));
 }

 public System.IAsyncResult BeginFactorize(long factorizableNum, System.AsyncCallback callback, object  asyncState) {
  return this.BeginInvoke(\"Factorize\", new object[] {
  factorizableNum}, callback, asyncState);
 }

 public long[] EndFactorize(System.IAsyncResult asyncResult) {
  object[] results = this.EndInvoke(asyncResult);
  return ((long[])(results[0]));
 }
}


  有两个方法用来和XML Web服务方法异步通信。下面的代码示例说明了如何与一个XML Web服务方法异步通信,并且使用回调函数来取得XML Web服务方法的结果。

[C#]
using System;
using System.Runtime.Remoting.Messaging;
using MyFactorize;

class TestCallback
{
 public static void Main(){
  long factorizableNum = 12345;
  PrimeFactorizer pf = new PrimeFactorizer();

  //Instantiate an AsyncCallback delegate to use as a parameter
  //in the BeginFactorize method.
  AsyncCallback cb = new AsyncCallback(TestCallback.FactorizeCallback);

  // Begin the Async call to Factorize, passing in our
  // AsyncCalback delegate and a reference
  // to our instance of PrimeFactorizer.
  IAsyncResult ar = pf.BeginFactorize(factorizableNum, cb, pf);

  // Keep track of the time it takes to complete the async call
  // as the call proceeds.
  int start = DateTime.Now.Second;
  int currentSecond = start;
  while (ar.IsCompleted == false){
   if (currentSecond < DateTime.Now.Second) {
    currentSecond = DateTime.Now.Second;
    Console.WriteLine(\"Seconds Elapsed...\" + (currentSecond - start).ToString() );
   }
  }
  // Once the call has completed, you need a method to ensure the
  // thread executing this Main function
  // doesn\'t complete prior to the call-back function completing.
  Console.Write(\"Press Enter to quit\");
  int quitchar = Console.Read();
 }
 // Set up a call-back function that is invoked by the proxy class
 // when the asynchronous operation completes.
 public static void FactorizeCallback(IAsyncResult ar)
 {
  // You passed in our instance of PrimeFactorizer in the third
  // parameter to BeginFactorize, which is accessible in the
  // AsyncState property.
  PrimeFactorizer pf = (PrimeFactorizer) ar.AsyncState;
  long[] results;

  // Get the completed results.
  results = pf.EndFactorize(ar);

  //Output the results.
  Console.Write(\"12345 factors into: \");
  int j;
  for (j = 0; j<results.Length;j++){
   if (j == results.Length - 1)
    Console.WriteLine(results[j]);
   else
    Console.Write(results[j] + \", \");
  }
 }
}

[Visual Basic]
Imports System
Imports System.Runtime.Remoting.Messaging
Imports MyFactorize

Public Class TestCallback
Public Shared Sub Main()
Dim factorizableNum As Long = 12345
Dim pf As PrimeFactorizer = new PrimeFactorizer()

\'Instantiate an AsyncCallback delegate to use as a parameter
\' in the BeginFactorize method.
Dim cb as AsyncCallback
cb = new AsyncCallback(AddressOf TestCallback.FactorizeCallback)

\' Begin the Async call to Factorize, passing in the
\' AsyncCallback delegate and a reference to our instance
\' of PrimeFactorizer.
Dim ar As IAsyncResult = pf.BeginFactorize(factorizableNum, cb, pf)

\' Keep track of the time it takes to complete the async call as
\' the call proceeds.
Dim start As Integer = DateTime.Now.Second
Dim currentSecond As Integer = start
Do while (ar.IsCompleted = false)
If (currentSecond < DateTime.Now.Second) Then
 currentSecond = DateTime.Now.Second
 Console.WriteLine(\"Seconds Elapsed...\" + (currentSecond - start).ToString() )
End If
Loop

\' Once the call has completed, you need a method to ensure the
\' thread executing this Main function
\' doesn\'t complete prior to the callback function completing.
Console.Write(\"Press Enter to quit\")
Dim quitchar As Integer = Console.Read()
End Sub

\' Set up the call-back function that is invoked by the proxy
\' class when the asynchronous operation completes.
Public Shared Sub FactorizeCallback(ar As IAsyncResult)

\' You passed in the instance of PrimeFactorizer in the third
\' parameter to BeginFactorize, which is accessible in the
\' AsyncState property.

Dim pf As PrimeFactorizer = ar.AsyncState
Dim results() as Long

\' Get the completed results.
results = pf.EndFactorize(ar)

\'Output the results.
Console.Write(\"12345 factors into: \")
Dim j as Integer
For j = 0 To results.Length - 1
 If j = (results.Length - 1) Then
  Console.WriteLine(results(j) )
 Else
  Console.Write(results(j).ToString + \", \")
 End If
Next j
End Sub
End Class


  下面的代码示例说明了如何与一个XML Web服务方法异步通信,然后使用一个同步对象来等待处理结束。

[C#]
// -----------------------------------------------------------------------// Async Variation 2.
// Asynchronously invoke the Factorize method,
//without specifying a call back.
using System;
using System.Runtime.Remoting.Messaging;
// MyFactorize, is the name of the namespace in which the proxy class is
// a member of for this sample.
using MyFactorize;

class TestCallback
{
 public static void Main(){
  long factorizableNum = 12345;
  PrimeFactorizer pf = new PrimeFactorizer();

  // Begin the Async call to Factorize.
  IAsyncResult ar = pf.BeginFactorize(factorizableNum, null, null);

  // Wait for the asynchronous operation to complete.
  ar.AsyncWaitHandle.WaitOne();

  // Get the completed results.
  long[] results;
  results = pf.EndFactorize(ar);

  //Output the results.
  Console.Write(\"12345 factors into: \");
  int j;
  for (j = 0; j<results.Length;j++){
   if (j == results.Length - 1)
    Console.WriteLine(results[j]);
   else
    Console.Write(results[j] + \", \");
  }
 }
}

[Visual Basic]
Imports System
Imports System.Runtime.Remoting.Messaging
Imports MyFactorize \' Proxy class namespace

Public Class TestCallback
Public Shared Sub Main()
Dim factorizableNum As Long = 12345
Dim pf As PrimeFactorizer = new PrimeFactorizer()

\' Begin the Async call to Factorize.
Dim ar As IAsyncResult = pf.BeginFactorize(factorizableNum, Nothing, Nothing)

\' Wait for the asynchronous operation to complete.
ar.AsyncWaitHandle.WaitOne()

\' Get the completed results.
Dim results() as Long
results = pf.EndFactorize(ar)

\'Output the results.
Console.Write(\"12345 factors into: \")
Dim j as Integer
For j = 0 To results.Length - 1
 If j = (results.Length - 1) Then
  Console.WriteLine(results(j) )
 Else
  Console.Write(results(j).ToString + \", \")
 End If
Next j
End Sub
End Class


  注意:如果FactorizeCallback是一个需要同步化/线成亲和上下文的上下文绑定类,那么回调被通过上下文分配体系结构来分配。换句话说,相对于它的对这样的上下文的调用者,回调可能异步的执行。在方法标记上有单向修饰词的精确的语义。这指的是任何这样的方法调用可能同步地或异步地执行,相对于调用者,并且在执行控制返回给它的时候,调用者不能产生任何关于完成这样一个调用的假设。
而且,在异步操作完成之前调用EndInvoke将阻塞调用者。使用相同的AsyncResult再次调用它的行为是不确定的。

  Cancel方法是一个在过去一段特定时间之后取消方法处理的请求。注意它是一个客户端的请求,并且最好服务器对此有所承诺。在接收到方法已经被取消的消息之后,客户端就不必做服务器是否已经停止处理的假设了。客户端最好不要破坏资源,例如文件对象,因为服务器可能仍然需要使用它们。IAsyncResult实例的IsCompleted属性在服务器结束它的处理之后将被设置为true,不再使用任何客户端提供的资源。因此,IsCompleted属性设置为true之后,客户端就可以安全的销毁资源了。

-= 资 源 教 程 =-
文 章 搜 索
关键词:
类型:
范围:
纯粹空间 softpure.com
Copyright © 2006-2008 暖阳制作 版权所有
QQ: 15242663 (拒绝闲聊)  Email: faisun@sina.com
 纯粹空间 - 韩国酷站|酷站欣赏|教程大全|资源下载|免费博客|美女壁纸|设计素材|技术论坛   Valid XHTML 1.0 Transitional
百度搜索 谷歌搜索 Alexa搜索 | 粤ICP备19116064号-1