结合抽象工厂模式的异步和非异步实现

时间:2018-05-08 11:37:14

标签: c# asp.net-mvc design-patterns async-await abstract-factory

我们的在线商店有一个ASP.Net MVC应用程序。用户必须从多种付款方式中进行选择才能购买。为此,我们实现了一个抽象工厂模式:

public interface IPaymentServiceFactory
{
    IPaymentService GetPaymentService(PaymentServiceEnum paymentServiceType);
}
public interface IPaymentService
{
    PaymentSettingsModel GetPaymentSettingsModel();
}

它用于我们的行动:

public ActionResult ProcessCart(PaymentDataModel paymentData)
{
    var paymentService = _paymentServiceFactory.GetPaymentService(paymentData.PaymentServiceType);
    var paymentSettings = paymentService.GetPaymentSettingsModel();
}

当我们了解某些付款方式需要内部异步调用时,就会出现问题。例如,必须通过http异步调用第三方在线支付服务方法来创建支付对象。实施:

    public class OnlinePaymentService : IPaymentService
    {
        private readonly IOnlinePaymentServiceApiClient _client;
        public async Task<PaymentSettingsModel> GetPaymentSettings()
        {
            var result =  await _client.CreatePaymentAsync();
            return result;
        }
    }

因此我们提出了一个问题:如何处理不同付款方式的异步和同步方案。我们决定让一切都异步。更新的代码:

public interface IPaymentService
{
    Task<PaymentSettingsModel> GetPaymentSettings();
}
public async Task<ActionResult> ProcessCart(PaymentDataModel paymentData)
{
    var paymentService = _paymentServiceFactory.GetPaymentService(paymentData.PaymentServiceType);
    var paymentSettings = await paymentService.GetPaymentSettingsModel();
}

到目前为止一切顺利,但为了实现所有其他付款方式,我们被迫使用Task.Run:

    public class CashPaymentService : IPaymentService
    {
        public async Task<PaymentSettingsModel> GetPaymentSettings()
        {
            return await Task.Run(() => new PaymentSettingsModel());;
        }
    }

据我所知,这会创建两个不同的线程来处理Action,这可能导致performance issue。 有办法避免这种后果吗?在特定情况下使用Task.Run真的很糟糕吗?

1 个答案:

答案 0 :(得分:3)

  

在特定情况下使用Task.Run真的很糟糕吗?

是的,主要是因为它不必要地使事情变得复杂。

您可以使用Task.FromResult返回已完成的任务,其结果为给定值。

这是完全同步的:

public class CashPaymentService : IPaymentService
{
    public Task<PaymentSettingsModel> GetPaymentSettings()
    {
        return Task.FromResult( new PaymentSettingsModel() );
    }
}

请注意,此处缺少async - 这是可能的,因为它是一个实现细节,而不是IPaymentService定义的一部分。