Reputation: 942
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!
Upvotes: 0
Views: 604
Reputation: 456507
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;
}
Upvotes: 3