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

Combine async and not async implementations for the abstract factory pattern

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

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

在我们的Action中使用:

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

当我们了解某些支付方式需要内部异步调用时,就会出现问题。例如第 3 方在线支付服务方法必须通过 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 真的很糟糕吗?

Is it really so bad to use Task.Run in particular case?

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

您可以 return 一个已完成的任务,其结果是使用 Task.FromResult 的给定值。

这是完全同步的:

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

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

定义的一部分