简体   繁体   English

在启动时调用 AddTransient 中的异步方法 - Asp.Net Core

[英]Call async method in AddTransient in Startup - Asp.Net Core

I have a service which is used to get some information and the method has a bunch of async calls in the chain.我有一个用于获取一些信息的服务,并且该方法在链中有一堆异步调用。

public interface IFooService
{
    Task<IFoo> GetFooAsync();
}

The concrete class,具体类,

public class FooService : IFooService
{
    public async Task<IFoo> GetFooAsync()
    {
        // whole bunch of awaits on async calls and return IFoo at last
    }
}

I register this service on StartUp,我在 StartUp 上注册了这个服务,

services.AddTransient<IFooService, FooService>();

Several other services are injected with this service.此服务注入了其他几个服务。 One among them,其中之一,

public class BarService : IBarService
{
    private readonly IFooService _fooService;

    public BarService(IFooService fooService)
    {
        _fooService = fooService;
    }

    public async Task<IBar> GetBarAsync()
    {
        var foo = await _fooService.GetFooAsync();

        // additional calls & processing
        var bar = SomeOtherMethod(foo);

        return bar;
    }
}

IFoo is integral to the application and used across several services. IFoo是应用程序不可或缺的一部分,并在多个服务中使用。 Most of my code is async just due to this one IFooService and the one method it has which returns IFoo .我的大部分代码都是async只是因为这个IFooService和它具有的一种返回IFoo

Considering this use case, I would like to be able to just inject IFoo to all other services as opposed to injecting them with IFooService .考虑到这个用例,我希望能够将IFoo注入所有其他服务,而不是将它们注入IFooService

I gave this a shot,我试了一下,

services.AddTransient<IFoo>(provider => 
{
    var fooService = provider.GetService<IFooService>();
    var foo = fooService.GetFooAsync().GetAwaiter().GetResult();
    return foo;
});

but it raises a red flag to me as I'm doing sync over async and I'm unsure if this will cause any issues like race conditions.但它向我提出了一个危险信号,因为我正在通过异步进行同步,我不确定这是否会导致任何问题,例如竞争条件。 Would startup be blocked by doing this.这样做会阻止启动。 Im looking for a clean way to handle this, any recommendation for when we need something like this?我正在寻找一种干净的方法来处理这个问题,当我们需要这样的东西时有什么建议吗? Thank you for your help.感谢您的帮助。

2 Other options 2 其他选​​项

  1. Inject Func<Task> as the transient, the caller can await !注入 Func<Task> 作为瞬态,调用者可以等待!

  2. Task.Run( async () await abc).Wait(); Task.Run( async() await abc).Wait(); // this deadlocks much less // 这种死锁要少得多
    due to creating a task and having less issues .由于创建任务并且问题较少。

but it raises a red flag to me as I'm doing sync over async但是当我通过异步进行同步时,它向我发出了危险信号

For this red flag, it is caused by that you call method GetFoo which is not defined in IFooService , it is not related with async or sync method.对于这个红旗,是由于您调用了GetFoo中未定义的IFooService ,与 async 或 sync 方法无关。

Try the method which is defined尝试定义的方法

services.AddTransient<IFoo>(provider =>
{
    var fooService = provider.GetService<IFooService>();
    var foo = fooService.GetFooAsync().Result;
    return foo;
});
services.AddTransient<IFoo>(provider =>
{
    var fooService = provider.GetService<IFooService>();
    var foo = fooService.GetFooAsync().GetAwaiter().GetResult();
    return foo;
});

This option is slightly better than .Result since .Result will wrap all your exceptions into AggregateException and you won't have this side effect with code I suggested.此选项比.Result稍好,因为.Result会将您的所有异常包装到AggregateException并且您不会对我建议的代码产生这种副作用。 Also don't forget both options won't run asynchronously, it will run synchronously blocking the thread也不要忘记这两个选项不会异步运行,它会同步运行阻塞线程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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