【问题标题】:Instantiate and Call WCF service Asynchronously异步实例化和调用 WCF 服务
【发布时间】:2014-11-13 15:17:42
【问题描述】:

我有一个用于实例化 WCF 服务并执行操作的辅助方法。这对于同步调用非常有用,并且确实减少了我的主类中的代码。但是,我正在尝试在对服务的异步调用上实现相同的方法,并且遇到了语法问题。

这是我正在使用的辅助方法:

    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();
            }
        }
    }

这是我从计时器经过的事件中对辅助方法进行的同步调用:

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

这是调用 GetVehicleStatus 方法的地方:

    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();
        ...
     }

这是 GetVehicleStatus 方法的当前主体:

    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;
    }

我想将同步调用中的相同主体应用于异步调用,这样我就不必在主类中初始化服务,并且可以在那里封装所有错误处理。在尝试将 GetVehicleStatus 方法转换为 UpdateVehicleStatuses 方法中的 lambda 表达式时,我遇到了语法问题。我还尝试修改 GetVehicleStatus 方法以使用辅助方法,但没有成功。我错过了什么?

谢谢!

【问题讨论】:

    标签: c# linq wcf asynchronous async-await


    【解决方案1】:

    您需要一个异步版本的辅助方法:

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

    此外,如果您需要支持返回值,那么您将需要另一个重载:

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

    那么你可以这样使用它:

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

    【讨论】:

    • 非常感谢。如此明显,但我就是看不到。我能够重构我的同步代码以使用与返回值相同的异步方法。我最终得到了一种实例化服务和调用操作的干净方法。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 2012-10-03
    • 1970-01-01
    • 2010-12-25
    • 2014-11-09
    • 2020-01-21
    • 2018-09-07
    相关资源
    最近更新 更多