在启动期间异步运行应用程序配置

问题描述 投票:0回答:1

我有一段代码配置了在应用程序启动期间必须执行的应用程序的一部分。不幸的是,这需要一些时间,所以我想将它作为后台操作运行以加速应用程序启动。幸运的是,它本身的配置可以单独运行并且不需要 UI 线程。稍后,有些组件依赖于配置完成,因此它们应该等待配置完成。

之前的代码

public class App
{
    public static Configuration Config { get; set; } = new Configuration();

    public static void Main()
    {
        Configure();
        // .... run other stuff
        var service = new Service();
    }

    private void Configure()
    {
        try
        {
            Config.Add(typeof(MyClass), nameof(MyClass.Property1), 4);
            Config.Add(typeof(MyClass), nameof(MyClass.Property2), 2);
            Config.Add(typeof(MyClass), nameof(MyClass.Property3), 42);
            // there are tons of these configurations which takes a few seconds to run
        }
        catch (Exception)
        {
            // show message to the user and shut down application
        }
    }
}

public class Service
{
    public Service()
    {
        var config = App.Config; // use config
    }
}

现在我想知道最好的方法是什么。我的初稿是这样的:

public class App
{
    public static Task ConfigurationTask { get; set; }
    public static Configuration Config { get; set; } = new Configuration();

    public static void Main()
    {
        ConfigurationTask = ConfigureAsync();
        // .... run other stuff
        var service = new Service();
    }

    private static async Task ConfigureAsync()
    {
        try
        {
            var task = Task.Run(() =>
            {
                Config.Add(typeof(MyClass), nameof(MyClass.Property1), 4);
                Config.Add(typeof(MyClass), nameof(MyClass.Property2), 2);
                Config.Add(typeof(MyClass), nameof(MyClass.Property3), 42);
                // there are tons of these configurations which takes a few seconds to run
            });
            await task;
        }
        catch (Exception)
        {
            // show message to the user and shut down application
        }
    }
}

public class Service
{
    public Service()
    {
        App.ConfigurationTask.Wait();
        var config = App.Config; // use config
    }
}

但我确信在服务中阻塞任务不是一个好主意。解决这个问题的最佳做法是什么?

c# async-await initialization
1个回答
0
投票

如果您需要为最终用户足够快地运行应用程序,跳过配置部分,那么

Lazy<T>
可能就是您要找的。

private static Lazy<Configuration> _config = new Lazy<Configuration>(Configure);

private static Configuration Configure()
{
    var config = new Configuration();
    try
    {
        config.Add(typeof(Configuration), nameof(Configuration.Property1), 4);
        config.Add(typeof(Configuration), nameof(Configuration.Property2), 2);
        config.Add(typeof(Configuration), nameof(Configuration.Property3), 42);
        // there are tons of these configurations which takes a few seconds to run
    }
    catch (Exception)
    {
        // show message to the user and shut down application
    }
    return config;
}

public static Configuration Config => _config.Value;

public static void Main()
{
    var service = new Service();
}
public class Service
{
    public Service()
    {
        // the Configure() will run at this moment.                
        var config = Config;
    }
}

通过上面的

Lazy<T>
,只有当
Add(agr1, agr2, agr3)
类被实例化并尝试引用
Service
成员时,才会执行大量的
Config
作业。

这是 MSDN 所说的。

使用惰性初始化来推迟大型或资源密集型对象的创建,或资源密集型任务的执行,特别是当此类创建或执行可能不会在程序的生命周期内发生时。

如果您需要尽可能快地初始化

Configuration
对象,那么第二个示例也可能没问题。更改构造函数的可能性更大,因为就像您提到的那样,阻塞线程不是一个好主意。

public class Service
{
    public async Task RunAsync()
    {
        await App.ConfigurationTask;
        var config = App.Config; // use config
        // do other stuff
    }
}
.
.
.
public static void Main()
{
    ConfigurationTask = ConfigureAsync();
    // .... run other stuff
    var service = new Service();
    await service.RunAync();
}
© www.soinside.com 2019 - 2024. All rights reserved.