0

A 3rd party has supplied an interface which allows me to search their database for customers and retrieve their details. Eg. Pictures, date of birth etc.

I imported their WSDL into Visual Studio and am using the Async methods to retrieve the customer details.

MyClient Client = new MyClient();
Client.FindCustomersCompleted += FindCustomersCompleted;
Client.GetCustomerDetailsCompleted += GetCustomerDetailsCompleted;

Client.FindCustomersAsync("Jones");

Below are the two events which deal with the responses.

void FindCustomersCompleted(object sender, FindCustomersCompletedEventArgs e)
{
    foreach(var Cust in e.Customers)
    {
        Client.GetCustomerDetailsAsync(Cust.ID);
    }
}

void GetCustomerDetailsCompleted(object sender, GetCustomerDetailsCompletedEventArgs e)
{
    // Add the customer details to the result box on the Window.
}

So lets assume that my initial search for "Jones" returns no results or causes an error. Its fairly straight forward to tell the user that there was an error or no results found as I will only receive a single response.

However if i say get 50 results for "Jones" then i make 50 GetCustomerDetailsAsync calls and get 50 responses.

Lets say that something goes wrong on the server side and i don't get any valid responses. Each GetCustomerDetailsCompleted event will receive an error/timeout and i can determine that that individual response has failed.

What is the best way to determine that All of my responses have failed and i need to inform the user that there has been a failure? Alternatively what if 1 out of 50 succeeds?

Should i keep track of my requests and flag them as successful as i receive the response?

CathalMF
  • 9,705
  • 6
  • 70
  • 106

2 Answers2

0

Should i keep track of my requests and flag them as successful as i receive the response?

This is also how I manage multiple requests. Flag if the returned result is without fault and track the flags, evaluating after each return if you already processed all returns. I do not of another way.

Wicher Visser
  • 1,513
  • 12
  • 21
0

I would start by converting Event-based Asynchronous Pattern model to Task based. This would allow to use built in await/async keywords resulting in much easier to use code.

Here is a simple implementation: https://stackoverflow.com/a/15316668/3070052

In your case I would not update UI on each event but gathered all the information in a single variable and only displayed only when I get all the results.

Here is a code to get you going:

public class CustomerDetails
{
    public int Id {get; set;}
    public string Name {get; set;}
}

public class FindCustomersResult
{
    public FindCustomersResult()
    {
        CustomerDetails = new List<CustomerDetails>();
    }
    public List<CustomerDetails> CustomerDetails {get; set;}
}

public class ApiWrapper
{
    public Task<FindCustomersResult> FindCustomers(string customerName)
    {
        var tcs = new TaskCompletionSource<FindCustomersResult>(); 
        var client = new MyClient();
        client.FindCustomersCompleted += (object sender, FindCustomersCompletedEventArgs e) => 
            {
                var result = new FindCustomersResult();

                foreach(var customer in e.Customers)
                {
                    var customerDetails = await GetCustomerDetails(customer.ID);
                    result.CustomerDetails.Add(customerDetails);
                }
                tcs.SetResult(result);
            }
        client.FindCustomersAsync(customerName);    
        return tcs.Task;
    }

    public Task<CustomerDetails> GetCustomerDetails(int customerId)
    {
        var tcs = new TaskCompletionSource<CustomerDetails>(); 
        var client = new MyClient();
        client.GetCustomerDetailsCompleted += (object sender, GetCustomerDetailsCompletedEventArgs e) => 
            {
                var result = new CustomerDetails();
                result.Name = e.Name;
                tcs.SetResult(result);
            }
        client.GetCustomerDetailsAsync(customerId); 
        return tcs.Task;
    }
}

Then you call this by:

var api = new ApiWrapper();
var findCustomersResult = await api.FindCustomers("Jones");

This would fail if any request fails.

PS. I wrote this example in notepad, so bear with me if it does not compiles or contains syntax errors. :)

Community
  • 1
  • 1
Kaspars Ozols
  • 6,967
  • 1
  • 20
  • 33