Home Products Download Events Support Registration

Home
Up

What should I use, asynchrony or synchrony?


UDAParts
support@udaparts.com
Updated on 10/06/2007

Contents

a.    Introduction
b.    Samples for C# and VB.NET
c.    How to use asynchrony computation
       Sending an asynchronous request
       Asynchronous request specialty
       Processing return result
d.    How to use synchrony computation in SocketPro
       Batch requests
       Wait, check status and reporting various errors
       Synchronous calls but no frozen windows
e.    Advantages and disadvantages of SocketPro asynchrony computation
       Advantages of asynchrony computation
       Disadvantages of asynchrony computation
       Offset flaws of SocketPro asynchrony computation
f.    Conclusion

1.    Introduction

    In most cases, we call various functions synchronously assuming an expected result is returned in a very short time. However, in reality, very often we are not happy to calling a function synchronously, especially when the function takes a long time to be processed. If you call such a slow function within a window application, the window application seems to be crash or dead to a user. A common but only way to most programmers to eliminate this problem is to use a worker thread to handle the long-time function in the background. However, this approach is very often painful to us because of thread side effects, synchronization, deadlock and bad code readability. With the help of SocketPro, you will not have thread-related problems at all because SocketPro is written with both asynchrony and synchrony computations in mind.

    In this article, we will focus on the following items:

        a.    How to use asynchrony computation,
        b.    How to use synchrony computation,
        c.    How to switch between asynchrony and synchrony computations,

2.    Samples for C# and VB.NET

    SocketPro contains samples inside the directory ..\samples\AsynSyn for both C# and VB.NET. After compiling these samples, put debug points, run them, and see code execution. All of sample codes in this article are excerpt from C# projects. The project AsynClient demonstrates processing requests in 100% asynchrony computation. The project SynClient shows how to convert asynchronous requests into synchronous ones. No matter you use asynchrony or synchrony computations, the server code is exactly the same.

3.    How to use asynchrony computation

    Sending an asynchronous request: By default, SocketPro uses asynchrony computation to handle all of requests from a client to a remote server and all of returned results from the server back to the client. Here is a piece of code from the sample AsynClient project to show you how to send a request asynchronously.

private int m_nErrorCode = 0;

private DataSet m_ds = null;

public void QueryRowsetAsyn(string strSQL)

{

    CUQueue UQueue = GetAttchedClientSocket().GetMemoryQueue();

    UQueue.SetSize(0);
    //write strSQL into memory queue

    UQueue.Save(strSQL);

    SendRequest(idQueryRowset, UQueue);

}

    As usually, we write all of input parameters data into a memory queue and send the request in binary to remote host and return immediately without any delay. In the above code sample, we get a memory queue (UQueue) from a CClientSocket object, initially set the memory queue size to zero, and pack all of input parameters into the memory queue. At last, we send the request in binary with a specified request id (idQueryRowset) onto a remote host. The call returns immediately without waiting for an expected result. 

    Asynchronous request specialty: Note that all of asynchronous request methods do not have any output parameters or return value as shown in the above sample. Instead, we define private data members (for example, m_ds and m_nErrorCode) to hold its return results. The number of data members is always equal to the number of expected output results. In this sample, the number of data members is two (m_ds and m_nErrorCode). 

    Processing return results: Once a remote server completes processing the request, the server sends its result back to the client. The client socket picks up the event when the returned result comes. It eventually causes the following function called:

protected override void OnResultReturned(short sRequestID, CUQueue UQueue)

{

    switch (sRequestID)

    {

        case idQueryRowset:
            m_ds =
null;

            UQueue.Pop(ref m_nErrorCode);  //unpack expected error code first

            if (m_nErrorCode == 0)

            {

                object obj = null;

                UQueue.Deserialize(ref obj); //unpack a DataSet if no error found

                m_ds = (DataSet)obj;

            }

            break;

        default:

            break;

   }

}

    Inside the function, we process the returned result. Take this as an example, First, we unpack an error code. If no error is found, we unpack a DataSet object. In SocketPro, all of requests are processed on client side exactly like the above without exception, no matter what a request is. Although requests may have different number of different input parameters, this pattern is never changed under any situations.
        

4.    How to use synchrony computation

    Batch requests: By default, SocketPro uses asynchrony computation to handle requests and returned results. Switching to synchrony computation is simply to call the method WaitAll or Wait under particular case. Here is sample code snippet excerpt from the project SynClient.

public DataSet QueryRowset(string strSQL)

{

    GetAttchedClientSocket().BeginBatching();

    QueryRowsetAsyn(strSQL);

    QueryLastErrorAsyn();

    GetAttchedClientSocket().Commit(true); //true -- ask server to send all results in batch

    WaitAndCheckStatus();

    return m_ds;

}

    Usually, we batch a number of asynchronous requests. Also, we ask a SocketPro server to send back results in batch. Take the above code snippet as a sample. We send two requests, QueryRowsetAsyn and QueryLastErrorAsyn, onto a remote server in batch. Afterwards, we force the server to return results back in batch. Finally, we call the method WaitAndCheckStatus to block until all of results come. Here is the implementation for the method WaitAndCheckStatus.

private void WaitAndCheckStatus()

{

    CClientSocket Socket = GetAttchedClientSocket();

    bool bWait = Socket.WaitAll();

    if (!bWait)

    {

        if (Socket.GetErrorCode() != 0)

        {

            //socket communication error

            throw new Exception(Socket.GetErrorMsg());

        }

        else if (!Socket.IsConnected())

        {

            throw new Exception("Socket is closed.");

        }

    }

    else if(m_strErrorMsg != null)

    {

        //data processing error

        throw new Exception(m_strErrorMsg);

    }

}

    Wait, check status and reporting various errors: After looking through the above two code snippets, you will see the method QueryRowset is synchronous method as usual methods. When the method QueryRowset returns, you get the returned result DataSet. Additionally, you may get exceptions for network communication error or data processing error. At this point, you may prefer the method QueryRowset to QueryRowsetAsyn, because the former is more intuitive to you. We design the method WaitAll (or Wait) to simplify your coding on purpose. You can reuse the above QueryRowset as below, excerpt from the project SynClient.

private void btnExecuteSQL_Click(object sender, EventArgs e)

{

    txtErrorMessage.Text = "Executing requests .....";

    try

    {

        if (bRowset.Checked)

        {

            DataSet ds = m_SynHandler.QueryRowset(txtSQL.Text);

            gvRowset.DataSource = ds;

            if (ds.Tables.Count > 0)

            {

                gvRowset.DataMember = ds.Tables[0].TableName;

            }

            else

            {

               gvRowset.DataSource = null;

                gvRowset.DataMember = null;

            }

        }

        else

        {

            m_SynHandler.ExecuteSimpleSQL(txtSQL.Text);

        }

        txtErrorMessage.Text = "Command " + txtSQL.Text + " executed successfully.";

    }

    catch (Exception eError)

    {

        txtErrorMessage.Text = eError.Message;

        gvRowset.DataSource = null;

        gvRowset.DataMember = null;

    }

}

    Synchronous calls but no frozen windows: Very different from common synchrony methods, all of SocketPro remoting methods do not block window graphic user interfaces by default. When a user sends a long-time request, client window application is still responsive even though you send a long-time request synchronously within SocketPro. Within SocketPro, when you call the method WaitAll or Wait, internally SocketPro dispatches various window messages in addition to monitoring network communication events. Although you send a  request synchronously, window user interfaces are still responsive. In case you like freezing window user interfaces, you can call the method DisableUI.

5.    SocketPro Asynchrony Computation Pros and Cons

    Both asynchrony and synchrony computations have their own advantages and disadvantages. None of the two computation is perfect under all of situations. However, if you can take advantage of their strong points and offset their flaws, they will give you a perfect result and remove many programming troubles.

    Advantages: SocketPro asynchrony computation offers you a set of key advantages -- performance, scalability, many features and highly responsive window graphic user interfaces. 

    First of all, asynchrony computation enables you to batch many requests as shown in all of samples and tutorials, which leads to excellent performance and scalability for developing distributed applications. 

    Second, SocketPro asynchrony computation enables you to easily create many specific features. For example, you can easily cancel a long lasting request both hard and softly but you can't get this feature with other common frameworks. 

    Third, asynchronous requests do not block window graphic user interfaces, and your window application must be very responsive to user events.

    Fourth, in many cases you can use asynchronous requests to avoid creating threads and their side effects. This is very useful for long-latency network having low bandwidth. If your networks are dial-up, DSL/Cable modems, and all types of WAN networks, asynchrony computation shows great advantages over synchrony computation.

    Fifth, you can easily execute multiple requests concurrently within one thread through asynchronous communication.

    Sixth, SocketPro asynchrony computation is especially great for exchanging large size of objects or collections of objects between two machines, as shown in the tutorial three, remote database service and remote window file service.

    All of the above strong points of asynchrony computation are weak points to synchrony computation.

    Disadvantages: In comparison to synchrony computation, the major problem of  asynchrony computation is not intuitive and code is scattered everywhere. Secondly, most of developers are not used to asynchrony programming style at the very beginning because we write absolutely most of codes with synchrony computation style only. Also, a minor problem is that asynchronous programming requires a little more code. 

    Contrarily, these weak points of asynchrony computation are strong points of synchrony computation.

    Offset flaws of asynchrony and synchrony computations for the best of two worlds: As listed in the above, asynchrony and synchrony computations are very supplementary to each others. We need such a framework to take advantage of their strong points and offset their flaws for the best of two worlds. SocketPro is indeed such a framework with two unique important methods WaitAll and Wait for converting one or a set of asynchronous requests into synchronous ones at your will. Take this sample as an example, you can see the code is more understandable in the project SynClient than in the project AsynClient. Our tool uidparser.exe automatically creates skeleton codes with synchrony calls for you.

6.    Conclusion

   SocketPro is default to asynchrony computation and has huge advantages over other synchrony frameworks in speed and features. You will never meet multithreading problems with SocketPro on client side. In reality, SocketPro will solve a lot of complex and challenging problems as shown in tutorials and various samples. In order to reduce the inconvenience of asynchrony computation under some cases, SocketPro also provides the special method WaitAll to convert a set of asynchronous requests into synchronous ones. Use of the method may reduce the inconvenience of asynchrony computation without considerably decreasing software performance or freezing window user interfaces.