.net 如何使用BackgroundService和Dependency Injection运行Winforms?

lmvvr0a8  于 2023-10-21  发布在  .NET
关注(0)|答案(2)|浏览(133)

我正在尝试启动分配给IHostBuilderservices.HostedServiceBackgroundService

IHostBuilder定义:

private static IHostBuilder CreateHostBuilder()
    {
        return Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddHostedService<LicenseControl>();

                services.AddTransient<Database>();
                services.AddTransient<CoreLicense>();

                services.AddSingleton<FormSelector>();

                services.AddTransient<ClienteForm>();
                services.AddTransient<GastoForm>();
                services.AddTransient<IngredienteForm>();
                services.AddTransient<ProdutoForm>();
                services.AddTransient<ReceitaForm>();
                services.AddTransient<RelatorioForm>();
                services.AddTransient<VendaForm>();
                services.AddTransient<MainForm>();
                services.AddTransient<ConfiguracoesForm>();
                services.AddTransient<UsuarioForm>();

                services.AddSingleton<AuthenticationForm>();
                
                services.AddScoped<IBridgeRepository, BridgeRepository>();
                services.AddScoped<IClienteRepository, ClienteRepository>();
                services.AddScoped<IGastoRepository, GastoRepository>();
                services.AddScoped<IIBGERepository, IBGERepository>();
                services.AddScoped<IIngredienteRepository, IngredienteRepository>();
                services.AddScoped<IProdutoRepository, ProdutoRepository>();
                services.AddScoped<IReceitaRepository, ReceitaRepository>();
                services.AddScoped<IVendaRepository, VendaRepository>();
                services.AddScoped<IUsuarioRepository, UsuarioRepository>();

                services.AddLogging(
                builder =>
                {
                    builder.AddFilter("Microsoft", LogLevel.Warning)
                           .AddFilter("System", LogLevel.Warning)
                           .AddFilter("NToastNotify", LogLevel.Warning)
                           .AddConsole();
                }
                );
            });
    }

但我发现启动HostedService的唯一可能方法是运行以下命令:

await CreateHostBuilder().Build().RunAsync();

最后,问题的发生是因为在这种方法中,线程锁定在那一行,不让我运行公共块代码来启动Form本身:

Application.Run(new MainForm());

如果我先运行Form,也会发生同样的情况,线程会锁定该行,不让我调用HostBuilderRunAsync
我还尝试在Form类上声明所有HostBuilder作用域,并在其构造函数上启动BackgroundService,但这样我就无法在ctor上运行Async方法。
我目前正在尝试(但尚未成功)调用Form而不使用Application。运行(仍然不知道这样做的所有副作用),以便我可以运行HostBuilder
我的整个程序类现在:

static class Program
{
    [STAThread]
    private static async Task Main()
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);            

        var host = CreateHostBuilder().Build();

        host.Services.GetRequiredService<AuthenticationForm>().Show();

        await host.RunAsync();
    }
    private static IHostBuilder CreateHostBuilder()
    {
        return Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddHostedService<LicenseControl>();

                services.AddTransient<Database>();
                services.AddTransient<CoreLicense>();

                services.AddSingleton<FormSelector>();

                services.AddTransient<ClienteForm>();
                services.AddTransient<GastoForm>();
                services.AddTransient<IngredienteForm>();
                services.AddTransient<ProdutoForm>();
                services.AddTransient<ReceitaForm>();
                services.AddTransient<RelatorioForm>();
                services.AddTransient<VendaForm>();
                services.AddTransient<MainForm>();
                services.AddTransient<ConfiguracoesForm>();
                services.AddTransient<UsuarioForm>();

                services.AddSingleton<AuthenticationForm>();
                
                services.AddScoped<IBridgeRepository, BridgeRepository>();
                services.AddScoped<IClienteRepository, ClienteRepository>();
                services.AddScoped<IGastoRepository, GastoRepository>();
                services.AddScoped<IIBGERepository, IBGERepository>();
                services.AddScoped<IIngredienteRepository, IngredienteRepository>();
                services.AddScoped<IProdutoRepository, ProdutoRepository>();
                services.AddScoped<IReceitaRepository, ReceitaRepository>();
                services.AddScoped<IVendaRepository, VendaRepository>();
                services.AddScoped<IUsuarioRepository, UsuarioRepository>();

                services.AddLogging(
                builder =>
                {
                    builder.AddFilter("Microsoft", LogLevel.Warning)
                           .AddFilter("System", LogLevel.Warning)
                           .AddFilter("NToastNotify", LogLevel.Warning)
                           .AddConsole();
                }
                );
            });
    }
}

考虑到.NET 5而忽略BackgroundWorker组件,对此有什么解决方案?

disbfnqx

disbfnqx1#

Nkosi的解决方案,评论:
创建另一个托管服务来调用Application.Run,这样当您运行主机时,UI方面和后台工作程序托管服务将启动

class StartProgram : BackgroundService
{
    private readonly IServiceProvider _services;
    public StartProgram(IServiceProvider services)
    {
        this._services = services;
    }
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run((AuthenticationForm)_services.GetService(typeof(AuthenticationForm)));

        return Task.CompletedTask;
    }
}

Program.cs:

static class Program
{
    [STAThread]
    private static async Task Main()
    {
        await CreateHostBuilder().Build().RunAsync();
    }
    private static IHostBuilder CreateHostBuilder()
    {
        return Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddHostedService<LicenseControl>();
                services.AddHostedService<StartProgram>();

                #region ETC...
            });
    }
}
gstyhher

gstyhher2#

我必须在服务集合中注册表单才能工作(在调用服务.AddHostedService()之后)。
public void run();

相关问题