Cancel asynchronous requests with progress reporting without losing session data
UDAParts
support@udaparts.com
Created on
11/15/2010

Introduction
SocketPro is written with requests batching, asynchronous and parallel computation in mind. One of many unique features is that you can easily implement cancelable computation with progress reporting without losing session data.
This simple sample is used to demonstrate the usage of this feature.
It is noted that the sample code for C++, C# and VB.NET is located at the directory of C:\Program Files (x86)\UDAParts\SocketPro\samples\RemoteSum after you install SocketPro package.
SocketPro universal interface definition file
Here is the content of the uid file named as RemoteSum.uid. The service named as RemSum contains two slow requests having dollar sign ahead, DoSum and RedoSum. The request Pause is a fast request.
[ServiceID = 10]
RemSum
{
$int DoSum(int start, int end);
int
Pause();
$int RedoSum();
}
The request DoSum is designed to sum all of integer numbers between the inputs start and end. Calling the request Pause will stop processing request DoSum or RedoSum and returns the result of sum at current time.
Create skeleton codes
for both client and server projects
You can follow the video tutorial one to create skeleton codes for both client and server projects by use of the tool uidparser.exe and the above uid file.
Manually add one id
for reporting progress from server to client
We need to manually add one request id into constants definition file (RemoteSum_i.cs) as the below.
public const
short idReportProgress = (idRedoSumRemSum + 1);
Analyze one code
snippet
The peer socket contains three session integer variables, m_nSum, m_nStart and m_nEnd, to track the current result of sum, the beginning of integer and the end of integer. The most important code snippet is listed as the below.
private int Compute()
{
int n;
for (n = m_nStart; n <= m_nEnd; ++n)
{
m_nSum
+= n;
System.Threading.Thread.Sleep(100); //simulate
slow request
int rtn = SendResult(RemoteSumConst.idReportProgress,
n, m_nSum);
if (rtn == CClientPeer.REQUEST_CANCELED
|| rtn == CClientPeer.SOCKET_NOT_FOUND)
break;
}
m_nStart
= (n + 1);
return m_nSum;
}
The code is
repeatedly pushing a message having a progress position (n) and its result of
sum (m_nSum)
with id equal to idReportProgress.
Also, SocketPro is monitoring the base request Cancel and socket closing event during
looping. When a client asks for canceling computation by sending a base request
Cancel, the method SendResult will return CClientPeer.REQUEST_CANCELED. If SocketPro detects the socket closed, it will return CClientPeer.SOCKET_NOT_FOUND.
SocketPro server will stop pushing message when it detects them or computation
is completed.
Display computing
progress and result of sum
At client side, we use the below code to report progress and computing result.
public void Process(CAsyncResult
AsyncResult)
{
switch
(AsyncResult.RequestId)
{
case
RemoteSumConst.idPauseRemSum:
case RemoteSumConst.idRedoSumRemSum:
case
RemoteSumConst.idDoSumRemSum:
{
int rtn = 0;
AsyncResult.UQueue.Pop(ref rtn);
txtSum.Text
= rtn.ToString();
}
break;
case
RemoteSumConst.idReportProgress:
{
int nWhere = 0;
int nSum = 0;
AsyncResult.UQueue.Pop(ref nWhere);
AsyncResult.UQueue.Pop(ref nSum);
txtSum.Text
= "Where = " + nWhere.ToString() +
", Sum = " + nSum.ToString();
}
break;
default:
break;
}
}
As you can
see, the above code snippet is very simple and highly understandable. We just
display results whenever there is a message with id equal to RemoteSumConst.idReportProgress from server side.
Cancel executing request
SocketPro implements a base request named as Cancel for canceling one or more
executing or queued requests at server side from a client. You can simply use
the below code to serve this purpose.
private void btnPause_Click(object sender, EventArgs
e)
{
m_cs.BeginBatching();
//send a cancel
request to a remote server. Here is a big secret from SocketPro!
m_cs.Cancel();
m_ash.SendRequest(RemoteSumConst.idPauseRemSum);
m_cs.Commit(true); //make two requests
in one shot
}
Test the
sample client and server applications
After
compiling the sample projects and running your SocketPro server first, you can
start the client application as shown in the above. After clicking the button
Do Sum, you will see the computing progress and the result of sum. Once you
click the button Pause, the
computation will stop, and will be restored if you click the button Redo Sum. No matter how many times you
start or stop computing, the final sum result is the same.
As you can see, this sample
demonstrates a simple implementation with the following key features.
·
Requests can be
canceled easily with SocketPro.
·
Session variables
can be kept and restored no matter how you stop and restore server
applications.
· You can easily track the computing progress by keeping on pushing messages from server onto client.
Other
examples for usage of cancel
This
is just a simple example for demonstration purpose only. Actually, you can use this
SocketPro feature to complete the following common tasks. This feature has
already been extensively used for load balancing in SocketPro.
· Canceling an executing long lasting database command from a client. Many database client APIs like MS SQL server, Oracle and DB2 support cancel executing command from a new thread.
· Canceling fetching a large set of records from a server to a client.
· Canceling downloading a large file from a server.
Further readings