Async Tasks over WCF

This is a sample of using async tasks over WCF.
The client handles possible errors (exceptions) from the server in a separate task.

Client.cs

        private async void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            txtResponse.Text = "";
            Task<string> t1 = null;
            Task<Task<string>> t2 = null;
            try
            {
                string testErr = "None";
                //testErr = "ThrowArgumentException";
                //testErr = "ThrowApplicationExceptionErr";

                t1 = SomeMethod(new SomeMethodRequest() { DocId = testErr });
                t2 = t1.ContinueWith<Task<string>>(ShowError, TaskContinuationOptions.OnlyOnFaulted);
                List<Task> tasks = new List<Task>() { t1, t2 };
                await Task.WhenAll(tasks);
                //Following is Not exec if faulted

                Debug.WriteLine("t1 status:" + t1.Id.ToString() + "-" + t1.Status);
            }
            catch (Exception ex)
            {
                //outer task (t1) is faulted - goto continue on faulted (t2)
            }
            finally
            {
                switch (t1.Status)
                {
                    case TaskStatus.RanToCompletion:
                        txtResponse.Text = t1.Result;
                        break;
                    case TaskStatus.Faulted: 
                        //Then the errortask ran
                        if (t2.Status == TaskStatus.RanToCompletion)
                        {
                            txtResponse.Text = t2.Result.Result;
                        }
                        break;
                    default:
                        break;
                }

                txtResponse.Text += "\r\n"+ "t1.Status:" + t1.Status;
                button1.Enabled = true;
            }
        }

        private async Task<string> SomeMethod(SomeMethodRequest request)
        {
            string retVal = "";
            try
            {
                //Using WCF service
                using (var svc = new MyService.MyServiceClient())
                {
                    //Exec Async service
                    //SomeMethodResponse x = await svc.SomeMethodAsync(request); or

                    Task<SomeMethodResponse> task = svc.SomeMethodAsync(request);
                    Debug.WriteLine("task:" + task.Id.ToString());
                    await Task.WhenAll(task);
                    //Following is Not exec if faulted

                    Debug.WriteLine("task status:" + task.Id.ToString() + "-" + task.Status);

                    if (task.Result != null)
                    {
                        //Status: RanToCompletion
                        retVal = "OperationSuccess: " + task.Result.OperationSuccess.ToString();
                    }
                    else
                    {
                        retVal = "Timed out" + "\r\n" + "Status: " + task.Status;
                    }
                }
            }
            catch (Exception ex)
            {
                //Fault the inner task by bubling up ex
                throw ex;
            }
            return retVal;
        }

        private async Task<string> ShowError(Task task)
        {
            string retVal = "";
            foreach (var ex in task.Exception.Flatten().InnerExceptions)
            {
                retVal += "\r\n" + "InnerEx: " + ex.Message;
            }
            //return Task.Factory.StartNew(() => retVal);

            return retVal;
        }

The server just runs in sync, but it can be changed to await some async response. The client already have just set up an Async call anyway.

When the server throws an error the task in the client will be faulted and the client takes action on that.
Server.cs

        public async Task<SomeMethodResponse> SomeMethod(SomeMethodRequest request)
        {
            try
            {
                //await Task.Delay(2000).ConfigureAwait(continueOnCapturedContext: false);

                if (request.DocId == "ThrowArgumentException")
                {
                    throw new ArgumentException("ArgumentException thrown");
                }
                if (request.DocId == "ThrowApplicationExceptionErr")
                {
                    throw new ApplicationException("ApplicationException Error when creating doc in target");
                }
                //ToDo: Do some stuff to retrieve a response
                var response = new SomeMethodResponse()
                {
                    OperationSuccess = true
                };

                return response;
                //return await Task.Run(() => response);
            }
            catch (Exception ex)
            {
                //Fault the service task by bubling up ex
                throw ex;
            }
        }

Links

The End.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: