简体   繁体   中英

Instantiate and Call WCF service Asynchronously

I have a helper method I am using to instantiate a WCF service and perform an action. This is working great for synchronous calls and has really cut down on the code in my main class. However, I am trying to implement this same method on an asynchronous call to the service and am having trouble with the syntax.

This is the helper method I am using:

    public static void Use(Action<T> action)
    {
        ChannelFactory<T> Factory = new ChannelFactory<T>("*");
        ClientCredentials Credentials = new ClientCredentials();
        Credentials.UserName.UserName = USER_NAME;
        Credentials.UserName.Password = PASSWORD;
        Factory.Endpoint.EndpointBehaviors.Remove(typeof(ClientCredentials));
        Factory.Endpoint.EndpointBehaviors.Add(Credentials);
        T Client = Factory.CreateChannel();
        bool Success = false;

        try
        {
            action(Client);
            ((IClientChannel)Client).Close();
            Factory.Close();
            Success = true;
        }
        catch (CommunicationException cex)
        {
            Log.Error(cex.Message, cex);
        }
        catch (TimeoutException tex)
        {
            Log.Error(tex.Message, tex);
        }
        finally
        {
            if (!Success)
            {
                ((IClientChannel)Client).Abort();
                Factory.Abort();
            }
        }
    }

This is the synchronous call I am making to the helper method from a timer elapsed event:

    async void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        Service<IVehicleService>.Use(client =>
        {
            Vehicles = client.GetAllVehicles(new GetAllVehiclesRequest()).vehicleList;
        });
        await UpdateVehicleStatuses();
    }

This is where the GetVehicleStatus method is called:

    private async Task UpdateVehicleStatuses()
    {
        // Can the call to GetVehicleStatus be turned into a lambda expression utilizing the helper method?
        IEnumerable<Task<VehicleStatus>> StatusQuery = from s in Vehicles 
                                                       select GetVehicleStatus(s.ClientVehicleId);
        List<Task<VehicleStatus>> StatusTasks = StatusQuery.ToList();
        ...
     }

This is the current body of the GetVehicleStatus method:

    private async Task<VehicleStatus> GetVehicleStatus(string clientVehicleID)
    {
        // Can this method be modified to use the helper method?
        GetStatusResponse Status = await VehicleClient.GetStatusByClientIdAsync(clientVehicleID);

        return Status.vehicleStatus;
    }

I would like to apply the same principal from the synchronous call to the asynchronous call so that I don't have to initialize the service in the main class and can encapsulate all of the error handling there. I am having trouble with the syntax when attempting to turn the GetVehicleStatus method into a lambda expression in the UpdateVehicleStatuses method. I have also tried to modify the GetVehicleStatus method to utilize the helper method with no luck. What am I missing?

Thanks!

You'll need an asynchronous version of your helper method:

public static async Task UseAsync(Func<T, Task> action)
{
    ...
    try
    {
        await action(Client);
        ...
}

Furthermore, if you need to support return values, then you'll need another overload:

public static async Task<TResult> UseAsync(Func<TClient, Task<TResult>> action)
{
    ...
    TResult result;
    try
    {
        result = await action(Client);
        ...
    return result;
}

Then you can use it as such:

private async Task<VehicleStatus> GetVehicleStatusAsync(string clientVehicleID)
{
    GetStatusResponse Status = await UseAsync(client => client.GetStatusByClientIdAsync(clientVehicleID));

    return Status.vehicleStatus;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM