Creating Asynchronous Web Methods

   


Creating Asynchronous Web Methods

Create and Consume an XML Web service: Create asynchronous Web methods.

If you simply call a Web service method from a client program (via a Web service proxy), the call is synchronous. That is, your client application will not process any other commands until the SOAP response comes back from the server. For example, if you click the Get Bug button from Step By Step 5.2 and then try to move the form, you'll discover that the form is unresponsive until the server response has been processed and displayed.

The proxy classes generated by Visual Studio .NET (or by wsdl.exe) also allow you to make asynchronous calls to a Web service. When you make an asynchronous call, the client sends the SOAP request, but it is not blocked waiting for the SOAP response. The Web service server does not require any special configuration to support asynchronous calls. In fact, as far as the server knows , the call is synchronous. All the additional processing is done at the client. The CLR sends the SOAP request and then monitors a system I/O completion port to wait for the SOAP response.

In this section, you'll see several ways to make an asynchronous call to a Web service. I'll also show you the code that the proxy class uses to enable asynchronous calls.

Using a Callback Delegate

The first way to handle an asynchronous Web method call is to provide a delegate that the runtime can invoke when the results are returned. Step by Step 5.4 illustrates this technique.

STEP BY STEP

5.4 Using a Callback Delegate for Asynchronous Web Method Calls

  1. Add a new form to the project that you created in Step By Step 5.2. Name the new form StepByStep5-4.vb.

  2. Place a Button control named btnGetBug and a TextBox control named txtDescription on the form. Set the Multiline property of the txtDescription control to True . Set the ScrollBars property of the control to Vertical .

  3. Double-click the button to open the form's module. Add this code to handle the button's Click event:

     Private Sub btnGetBug_Click(_  ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles btnGetBug.Click     ' Connect to the Web service     Dim B As localhost.Bugs = New localhost.Bugs()     ' Create a delegate to handle the callback     Dim cb As AsyncCallback = _      New AsyncCallback(AddressOf WebServiceCallback)     ' Launch the asynchronous call     B.BeginGetBug(1, cb, B)     ' Do some work while waiting for it to return     Dim intI As Integer     For intI = 1 To 100         txtDescription.AppendText(CStr(intI) & vbCrLf)     Next End Sub 
  4. Add code to implement the callback function:

     ' Callback to handle the asynchronous return Private Sub WebServiceCallback(_  ByVal ar As IAsyncResult)     ' Get the returned Web service instance     Dim B As localhost.Bugs     B = ar.AsyncState     ' Finish the work     Dim b1 As localhost.Bug = B.EndGetBug(ar)     ' And display the result     txtDescription.AppendText(b1.Description & vbCrLf) End Sub 
  5. Open the Reference.vb proxy class and remove the SoapDisplayExtension attribute from the GetBug method:

     <System.Web.Services.Protocols. _  SoapDocumentMethodAttribute(_  "http://BugTracker.que.com/GetBug", _  RequestNamespace:="http://BugTracker.que.com/", _  ResponseNamespace:="http://BugTracker.que.com/", _  Use:=System.Web.Services.Description. _  SoapBindingUse.Literal, _  ParameterStyle:= _  System.Web.Services.Protocols. _  SoapParameterStyle.Wrapped)> _ Public Function GetBug(ByVal BugID As Integer) As Bug     Dim results() As Object = _      Me.Invoke("GetBug", New Object() {BugID})     Return CType(results(0), Bug) End Function 
  6. Set the form as the startup object for the project.

  7. Run the project. Click the button on the default form. This will invoke the Web method asynchronously. You'll see the output of the other work before the Web service return value, as shown in Figure 5.6.

    Figure 5.6. Calling a Web method asynchronously.

The callback function for an asynchronous Web method call must have the signature shown in Step By Step 5.4, taking a single argument of type IAsyncResult. For each Web method, the proxy class will contain corresponding Begin and End methods. The Begin method takes all the arguments of the original method, plus a reference to the Web service object itself (necessary because you can have multiple asynchronous calls outstanding at any given time) and the address of the callback method (contained in an AsyncCallback object). When the results of the call are available, the callback method will be invoked. Within the callback method, you can retrieve the original Web service object and then call its End method to get the result of the method call.

NOTE

Asynchronous Is Unpredictable There's no guarantee that the project will print all 100 numbers to the TextBox control before the Web method returns; it depends on how fast your network is, how heavily loaded your computer is, and so on.


Using the WaitHandle Object

You can also use a WaitHandle object to manage asynchronous Web method calls. The WaitHandle essentially lets you turn the asynchronous process back into a synchronous process, as shown in Step By Step 5.5.

STEP BY STEP

5.5 Using a WaitHandle Object with Asynchronous Web Method Calls

  1. Add a new form to the project. Name the new form StepByStep5-5.vb.

  2. Place a Button control named btnGetBug and a TextBox control named txtDescription on the form. Set the Multiline property of the txtDescription control to True . Set the ScrollBars property of the control to Vertical .

  3. Double-click the button to open the form's module. Add this directive at the top of the module:

     Imports System.Threading 
  4. Add this code to handle the button's Click event:

     Private Sub btnGetBug_Click(_  ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles btnGetBug.Click     ' Connect to the Web service     Dim B As localhost.Bugs = New localhost.Bugs()     ' Create a result object to handle the callback     Dim ar As IAsyncResult     ' Launch the asynchronous call     ar = B.BeginGetBug(1, Nothing, Nothing)     ' Do some work while waiting for it to return     Dim intI As Integer     For intI = 1 To 90         txtDescription.AppendText(CStr(intI) & vbCrLf)     Next     ' Now wait for the method to come back     Dim wh As WaitHandle = ar.AsyncWaitHandle     wh.WaitOne()     Dim b1 As localhost.Bug = B.EndGetBug(ar)     ' And display the result     txtDescription.AppendText(b1.Description & vbCrLf)     ' Do some final work     For intI = 91 To 100         txtDescription.AppendText(CStr(intI) & vbCrLf)     Next End Sub 
  5. Set the form as the startup object for the project.

  6. Run the project. Click the button on the default form. This will invoke the Web method asynchronously. You'll see the output of the other work before and after the Web service return value, as shown in Figure 5.7. You'll still see some delay when the initial request is sent to the Web service.

    Figure 5.7. Waiting for the results of an asynchronous call.

In Step by Step 5.5, I didn't use a callback function at all. Rather, I used the BeginGetBug method to start the asynchronous method call and saved the result from this call as an IAsyncResult object.

When I was ready to wait for the results of the call, I retrieved a WaitHandle object from this object's AsyncWaitHandle property. The WaitOne method of this object causes the thread to pause until the results are ready.

EXAM TIP

Waiting for Multiple Results If you have multiple outstanding asynchronous Web method calls, you can wait for them all to come back by using the static WaitHandle.WaitAll method or wait for the first one to return by using the static WaitHandle.WaitAny method.


There are two other ways that you can manage asynchronous Web method calls if you like:

  1. You can use a loop to poll the value of the IAsyncResult.IsCompleted property. This property will return False while the method is still doing work and True when the End method is ready to call.

  2. You can simply call the End method in your code when you're ready to wait synchronously for the result. This is equivalent to using the WaitHandle.WaitOne method that you saw in Step By Step 5.5.

Inside the Asynchronous Proxy Methods

Although you probably won't need to write your own asynchronous methods, it's worth having a look at the code that Visual Studio .NET or wsdl.exe builds for you to create these methods. Here are the BeginGetBug and EndGetBug methods from the sample project that I've been working with:

 Public Function BeginGetBug(ByVal BugID As Integer, _  ByVal callback As System.AsyncCallback, _  ByVal asyncState As Object) As System.IAsyncResult     Return Me.BeginInvoke("GetBug", _      New Object() {BugID}, callback, asyncState) End Function Public Function EndGetBug(_  ByVal asyncResult As System.IAsyncResult) As Bug     Dim results() As Object = Me.EndInvoke(asyncResult)     Return CType(results(0), Bug) End Function 

The proxy class is derived from the SoapHttpClientProtocol class. The Begin and End methods are simply light wrappers around the generic BeginInvoke and EndInvoke methods provided by the base class.

The work performed in the specific methods consists of converting things to and from the parameter types used by the generic classes. BeginInvoke takes the name of the Web method being called, an array of objects that represent the parameters of the method, a callback delegate, and an arbitrary object passed from the caller. EndInvoke returns the results of the call as an array of objects. The return wrapper extracts items from this arrayhere, the single item stored in results(0)and casts them back to the data types that the caller is expecting.

GUIDED PRACTICE EXERCISE 5.1

The .NET Framework also makes provisions for aborting an asynchronous Web method call. To abort an asynchronous Web method call, you can cast the applicable IAsyncResult to a WebClientAsyncResult object and call the Abort method of the latter object.

In this exercise, you should create a form that calls the GetBug method. The form should call the method asynchronously and perform some processing after the method call. You should also add a button to the form that will abort the asynchronous call if the button is pressed before the result of the call is available.

You should try doing this on your own first. If you get stuck, or you'd like to see one possible solution, follow these steps:

  1. Add a new form to the project. Name the new form GuidedPracticeExercise5-1.vb.

  2. Place two Button controls named btnGetBug and btnAbort and a TextBox control named txtDescription on the form. Set the Multiline property of the txtDescription control to True . Set the ScrollBars property of the control to Vertical . Set the Enabled property of btnAbort to False .

  3. Double-click one of the button controls to open the form's module. Add this directive at the top of the module:

     Imports System.Web.Services.Protocols 
  4. Add this code to handle the events on the form:

     Dim ar As IAsyncResult Dim fAborted As Boolean Private Sub btnGetBug_Click(_  ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles btnGetBug.Click     ' Connect to the Web service     Dim B As localhost.Bugs = New localhost.Bugs()     ' Create a delegate to handle the callback     Dim cb As AsyncCallback = _      New AsyncCallback(AddressOf WebServiceCallback)     ' Launch the asynchronous call     ar = B.BeginGetBug(1, cb, B)     btnAbort.Enabled = True     fAborted = False     ' Do some work while waiting for it to return     Dim intI As Integer     For intI = 1 To 100         txtDescription.AppendText(CStr(intI) & vbCrLf)     Next End Sub ' Callback to handle the asynchronous return Private Sub WebServiceCallback(_  ByVal ar As IAsyncResult)     If Not fAborted Then         btnAbort.Enabled = False         ' Get the returned Web service instance         Dim B As localhost.Bugs         B = ar.AsyncState         ' Finish the work         Dim b1 As localhost.Bug = B.EndGetBug(ar)         ' And display the result         txtDescription.AppendText(b1. _          Description & vbCrLf)     End If End Sub Private Sub btnAbort_Click(_  ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles btnAbort.Click     ' Retrieve an appropriate object     Dim w As WebClientAsyncResult = ar     ' and call its Abort method     w.Abort()     fAborted = True     btnAbort.Enabled = False End Sub 
  5. Set the form as the startup object for the project.

  6. Run the project. Click the Get Bug button. When the code enables the Abort button, click the Abort button. The loop will display its results, but the Web service will not return any results.

REVIEW BREAK

  • By default, calls to a Web method are synchronous, and block the client program until the SOAP response is returned.

  • Proxies generated by wsdl.exe also allow you to make asynchronous calls to a Web service.

  • One way to make an asynchronous Web Method call is to supply a delegate function that the .NET Framework will call back when the SOAP response is ready.

  • Another way to make an asynchronous Web Method call is to use a WaitHandle object to wait for one or more calls to complete.

  • Asynchronous Web method calls can be aborted by calling the Abort method of an appropriate WebClientAsyncResult object.


   
Top


MCAD. MCSD Training Guide (Exam 70-310. Developing XML Web Services and Server Components with Visual Basic. NET and the. NET Framework)
MCAD/MCSD Training Guide (70-310): Developing XML Web Services and Server Components with Visual Basic(R) .NET and the .NET Framework
ISBN: 0789728206
EAN: 2147483647
Year: 2002
Pages: 166

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net