简体   繁体   English

在 ASP.Net Core 应用程序启动期间运行异步代码

[英]Run async code during startup in a ASP.Net Core application

After changing the signature of the function ConfigureServices to be asynchronous (originally it was just a void synchronous function and the application worked perfectly fine), I get the following error:在将 function ConfigureServices的签名更改为异步后(最初它只是一个 void 同步 function 并且应用程序运行良好),我收到以下错误:

Unable to find the required services.找不到所需的服务。 Please add all the required services by calling IServiceCollection.AddAuthorization inside the call to ConfigureServices(...) in the application startup code.请通过在应用程序启动代码中对ConfigureServices(...)的调用中调用IServiceCollection.AddAuthorization添加所有必需的服务。

Below is the code of my ConfigureServices function.下面是我的ConfigureServices function 的代码。

// This method gets called by the runtime. Use this method to add services to the container.
public async Task ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    // Create the necessary Cosmos DB infrastructure
    await CreateDatabaseAsync();
    await CreateContainerAsync();
}

ConfigureServices is automatically called at runtime. ConfigureServices在运行时自动调用。

You can't just change the signature, it needs to be void to be called by the framework.您不能只更改签名,它必须是无效的才能被框架调用。

Right now when you changed it to Task it means that the framework can't find it so it will not be called at all.现在,当您将其更改为 Task 时,这意味着框架找不到它,因此根本不会调用它。

There's a GitHub issue regarding this here: https://github.com/dotnet/aspnetcore/issues/5897这里有一个 GitHub 问题: https://github.com/dotnet/aspnetcore/issues/5897

It's quite tricky though...虽然这很棘手......

There's no progress for 5.0 no, we don't know how to do this without blocking or breaking changes. 5.0 没有进展 不,我们不知道如何在不阻止或破坏更改的情况下做到这一点。 It might be possible to run filters in 2 stages that never overlap.可以在从不重叠的 2 个阶段运行过滤器。

Update based on your comment: If you want to run something async during startup, I usually do like this:根据您的评论进行更新:如果您想在启动期间运行异步操作,我通常会这样做:

I create a interface like this:我创建一个这样的界面:

public interface IStartupTask
{
     Task Execute();
}

Then a sample implementation like this然后是这样的示例实现

public class CreateDatabaseStartupTask : IStartupTask
{
    public async Task Execute()
    {
          // My logic here
          // await CreateDatabaseAsync();
    }
}

Then in my Program.cs然后在我的 Program.cs

public static async Task Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();
    
    // Resolve the StartupTasks from the ServiceProvider
    var startupTasks = host.Services.GetServices<IStartupTask>();
    
    // Run the StartupTasks
    foreach(var startupTask in startupTasks)
    {
        await startupTask.Execute();
    }
    await host.RunAsync();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
}

And my Startup还有我的初创公司

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IStartupTask, CreateDatabaseStartupTask>();
    }
}

So the important things are:所以重要的是:

  1. Register your StartupTasks注册您的 StartupTasks
  2. Build the host构建主机
  3. Resolve the StartupTasks解决 StartupTasks
  4. Run the StartupTasks运行启动任务
  5. Start the Host启动主机

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

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