dot.NET.Framework.Essentials.1002003,.3Ed [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

dot.NET.Framework.Essentials.1002003,.3Ed [Electronic resources] - نسخه متنی

Hoang Lam; Thuan L. Thai

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










6.5 Async Web Services


All of the web service client examples we've used so
far make a call to the web service and wait for data before
continuing work. While this approach might be appropriate for small,
quick calls, such synchronous calls might yield an unacceptable
response time. The web service has to perform a time-consuming task.
Asynchronous web service calls are the answer in this case. This
section explores how the .NET Framework web services enable clients
to call web methods asynchronously, yielding a better overall
response time for an application.

If you look back at the generated source for the web service proxy in
the previous section, you will find that for every web method there
are three separate proxy methods generated. The following shows the
three proxy methods: GetAuthors( ),
BeginGetAuthors( ), and EndGetAuthors(
)
:

public System.Data.DataSet GetAuthors( ) {
object[] results = this.Invoke("GetAuthors", new object[0]);
return ((System.Data.DataSet)(results[0]));
}
public System.IAsyncResult BeginGetAuthors(System.AsyncCallback callback,
object asyncState) {
return this.BeginInvoke("GetAuthors",new object[0],callback,asyncState);
}
public System.Data.DataSet EndGetAuthors(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((System.Data.DataSet)(results[0]));
}

In the earlier web service consumer example, we've
used the proxy method GetAuthors( ) to call the
web method on the other side of the HTTP channel. The following
example shows how the other two methods can be used to perform an
asynchronous web method call.

As it turns out, there are a couple of different ways to use the
BeginMethodName(
)
and
EndMethodName(
)
to call the web method asynchronously. We will show you
each one and describe how they are different from one another.

The first way will be calling
BeginMethodName(
)
passing in null for both the callback
and the asyncState objects. We will poll on the IAsyncResult object
until it is completed while simulating other works. When the call is
done, we call
EndMethodName(
)
to complete the web method call and obtain the DataSet
result:[17]

[17] The proxy in this example was generated with
a namespace "WSPubsWS" instead of
the default global namespace.


WSPubsWS.PubsWS oProxy = new WSPubsWS.PubsWS( );
IAsyncResult result;
// Async call polling (cannot run this in debugger)
Console.Write("Async Polling");
result = oProxy.BeginGetAuthors(null, null);
while(!result.IsCompleted) {
Console.Write(" . . . "); Thread.Sleep(5);
}
DataSet oDSAsync = oProxy.EndGetAuthors(result);
oDSAsync.WriteXml("outputpolling.xml");
Console.WriteLine("done");

Although this might not be the best way, it demonstrates one way of
performing an asynchronous call to a web method.

The second way still does not use the callback mechanism. Be patient.
Again, we use the IAsyncResult object to perform a block waiting on
the remote call. Block waiting put the current thread to sleep,
giving up the CPU to other processes or threads until the wait handle
is signaled. Depending on your application, this might be how you
would want to do it:

// Async call with waithandle
Console.WriteLine("Async, processing then wait for handle");
result = oProxy.BeginGetAuthors(null, null);
Console.WriteLine(" . . . Processing some more . . . ");
result.AsyncWaitHandle.WaitOne( ); // block on handle
DataSet oDSAsyncWait = oProxy.EndGetAuthors(result);
oDSAsyncWait.WriteXml("outputWaiting.xml");
Console.WriteLine("done");

The third and fourth ways use the callback mechanism so we will know
exactly when to complete the web method call with the
EndMethodName(
)
. We make the call to the
BeginMethodName(
)
passing in the callback delegate. When the web method
call completes, we will get called back. Since this example is done
as a console application, a little more setting up is required;
otherwise, the application might exit before the callback occurs.
This is done through the AutoResetEvent object (a synchronization
primitive similar to a mutex). Basically, we want to set up a wait
object, call the async web method, and wait for the signal from the
callback before continuing with the application:

// Async call with callback 1
AutoResetEvent oWait = new AutoResetEvent(false);
Console.WriteLine("Async, processing then wait for callback");
CallBack cb = new CallBack(oProxy, oWait);
Result =oProxy.BeginGetAuthors(new AsyncCallback(cb.CallBackMethod), null);
Console.WriteLine(" . . . Processing some more . . . ");
Console.WriteLine("Application waits for callback rendezvous");
oWait.WaitOne( );
Console.WriteLine("done");

The CallBack class needs to have the proxy to complete the web method
call. It also needs the AutoResetEvent to signal the main application
flow to continue. The following is the definition of the CallBack
class at this moment:

public class CallBack {
public CallBack(WSPubsWS.PubsWS oProxy, AutoResetEvent oWait) {
m_oProxy = oProxy;
m_oWait = oWait;
}
public void CallBackMethod(IAsyncResult result) {
DataSet oDSAsyncCB;
oDSAsyncCB = m_oProxy.EndGetAuthors(result);
oDSAsyncCB.WriteXml("outputCallback.xml");
m_oWait.Set( );
}
private WSPubsWS.PubsWS m_oProxy;
private AutoResetEvent m_oWait;
}

In the next example, we pass both the callback and the asyncState
object to the
BeginMethodName(
)
method. We already know all about the callback object.
What about this asyncState thing? It actually can be
anything you want to pass to the callback
object. We will pass the proxy object itself via this asyncState
object so we will know how to complete the web method call when the
callback is invoked. The following code segment shows how this is
done:

// async call with callback 2
oWait.Reset( );
Console.WriteLine("Async, processing then wait for callback also");
CallBack cbWithData = new CallBack(oWait);
result=oProxy.BeginGetAuthors(new AsyncCallback(cbWithData.CallBackMethod), oProxy);
Console.WriteLine("Processing some more data");
Console.WriteLine("Application waits for callback rendezvous");
oWait.WaitOne( );
Console.WriteLine("done");

This time, the CallBack object is instantiated with only one
parameter. Changes to the CallBack class are highlighted in the
following code block. When the callback method is invoked, you can
cast the IAsyncResult object's AsyncState back to
whatever type you passed into the second parameter of the
BeginMethodName(
)
method. In this case, we cast the AsyncState object back
to the proxy in order to complete the web method call with
EndMethodName(
)
to obtain the resulting DataSet:

public class CallBack {
public CallBack(WSPubsWS.PubsWS oProxy, AutoResetEvent oWait) {
m_oProxy = oProxy;
m_oWait = oWait;
}
public CallBack(AutoResetEvent oWait) {
m_oWait = oWait;
}
public void CallBackMethod(IAsyncResult result) {
DataSet oDSAsyncCB;
if(m_oProxy == null) {
WSPubsWS.PubsWS oTmp = (WSPubsWS.PubsWS)result.AsyncState;
oDSAsyncCB = oTmp.EndGetAuthors(result);
oDSAsyncCB.WriteXml("outputCallbackWithData.xml");
} else {
oDSAsyncCB = m_oProxy.EndGetAuthors(result);
oDSAsyncCB.WriteXml("outputCallback.xml");
}
m_oWait.Set( );
}
private WSPubsWS.PubsWS m_oProxy;
private AutoResetEvent m_oWait;
}

In a Windows Form application, you can start the web service call via
a button clicked or a menu clicked and still can have other parts of
the application be responsive to the user. We will leave that example
to you as an exercise.


/ 121