三行代码  ›  专栏  ›  技术社区  ›  TCPW01

等待任务。何时自动关闭程序

  •  0
  • TCPW01  · 技术社区  · 1 月前

    我有一个方法,做铬浏览器初始化。运行两个异步方法后,程序自动关闭。我用过这个吗 Task.WhenAll 错误的

    Start.cs

    static class Start
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Initializer.Start();
            }
        }
    

    public static class Initializer
        {
            public static async void Start()
            {
                // The task that automatically close the program.
                Task<bool> chromiumInitTask = ChromiumInfo.InitializeAsync();
                await chromiumInitTask;
    
                Task webviewInitTask = WebViewInfo.InitializeAsync();
    
                Task guiInitTask = GUIInfo.InitializeAsync();
    
                HardwareManager.Initialize();
    
                await webviewInitTask;
    
                await guiInitTask;
    
                GUIInfo.Layout.ChangeMainDisplay(ChromiumInfo.Browser);
                Application.Run(GUIInfo.Layout.GetLayoutForm());
            }
        }
    

    ChromiumInfo.cs

    public static class ChromiumInfo
        {
            private static CefSettings _settings;
            private static ChromiumWebBrowser _browser;
            private static BrowserSettings _browserSettings;
            private static Dictionary<string, bool> _initTasks = new Dictionary<string, bool>()
            {
                { "Settings", false },
                { "Browser Settings", false },
                { "Browser", false },
                { "Cef", false }
            };
            private static KeyboardHandler _keyboardHandler;
    
            /// <summary>
            /// An setting which using on initialize.
            /// </summary>
            public static CefSettings Setting => _settings;
    
            /// <summary>
            /// Representing a browser which can be show in UI.
            /// </summary>
            public static ChromiumWebBrowser Browser => _browser;
    
            /// <summary>
            /// A keyboard handler which handle various keyboard events.
            /// </summary>
            public static KeyboardHandler KeyboardHandler => _keyboardHandler;
    
            /// <summary>
            /// Occur when request to change the browser.
            /// </summary>
            public static event RequestChangeBrowserEventHandler RequestChangeBrowser;
    
            /// <summary>
            /// Initialize all Chromium components in asynchronously.
            /// </summary>
            /// <param name="initAllScripts">Indicate should initialize all scripts contain in the root script directory.</param>
            /// <returns>Return a task can be awaited. True means sucess. Otherwise, return false.</returns>
            public static async Task<bool> InitializeAsync(bool initAllScripts = true)
            {
                Task settingInit = SettingsInitializeAsync();
                Task browserSettingInit = BrowserSettingsInitializeAsync();
                // The below line that automatically close the program.
                await Task.WhenAll(settingInit, browserSettingInit);
                
                Task cefInit = Cef.InitializeAsync(_settings);
                await cefInit;
                _initTasks["Cef"] = true;
    
                Task browserInit = BrowserInitializeAsync();
                await browserInit;
    
                Task eventInit = EventInitializeAsync();
                await eventInit;
    
                Task scriptInit = ScriptInitializeAsync();
                await scriptInit;
    
                return _initTasks.Values.Where(it => it).Count() == _initTasks.Count;
            }
    
            private static async Task SettingsInitializeAsync()
            {
                try
                {
                    _settings = new CefSettings();
    
                    _settings.CommandLineArgsDisabled = false;
                    _settings.CefCommandLineArgs.Clear();
                    _settings.CefCommandLineArgs.Add("enable-3d-apis", "1");
                    _settings.CefCommandLineArgs.Add("enable-webgl-draft-extensions", "1");
                    _settings.CefCommandLineArgs.Add("enable-gpu", "1");
                    _settings.CefCommandLineArgs.Add("enable-webgl", "1");
                    _settings.CefCommandLineArgs.Add("gpu_compositing", "1");
                    _settings.CefCommandLineArgs.Add("ignore-gpu-blocklist", "1");
    
                    await Task.Delay(1000).ConfigureAwait(false);
                    _initTasks["Settings"] = true;
                }
                catch (Exception e)
                {
                    SystemLog.Write(e);
                }
            }
    
            private static async Task BrowserSettingsInitializeAsync()
            {
                try
                {
                    _browserSettings = new BrowserSettings();
                    _browserSettings.WebGl = CefState.Enabled;
                    await Task.Delay(1000).ConfigureAwait(false);
    
                    _initTasks["Browser Settings"] = true;
                }
                catch (Exception e)
                {
                    SystemLog.Write(e);
                }
            }
    
            private static async Task BrowserInitializeAsync()
            {
                try
                {
                    _browser = new ChromiumWebBrowser(Properties.Settings.Default.DefaultURL);
                    _browser.BrowserSettings = _browserSettings;
                    _browser.Dock = System.Windows.Forms.DockStyle.Fill;
                    await Task.Delay(1000).ConfigureAwait(false);
    
                    _initTasks["Browser"] = true;
                }
                catch (Exception e)
                {
                    SystemLog.Write(e);
                }
            }
    
            private static async Task EventInitializeAsync()
            {
                KeyboardHandler keyboardHandler = new KeyboardHandler();
                WebCommandHandler commandHandler = new WebCommandHandler();
                _browser.ConsoleMessage += keyboardHandler.Handle;
                _browser.ConsoleMessage += commandHandler.Handle;
                _browser.AddressChanged += Custom_AddressChanged;
                _keyboardHandler = keyboardHandler;
                await Task.Delay(1000).ConfigureAwait(false);
            }
    
            private static async Task ScriptInitializeAsync()
            {
                string scriptPath = $@"{ProgramInfo.RootPath}\scripts";
                if (Directory.Exists(scriptPath))
                {
                    var files = Directory.GetFiles(scriptPath, "*.js");
                    files?.ToList().ForEach(f => _browser.GetMainFrame().ExecuteJavaScriptAsync(f, _browser.Address));
                }
    
                await Task.Delay(1000).ConfigureAwait(false);
            }
    
            private static void Custom_AddressChanged(object sender, AddressChangedEventArgs e)
            {
                var wv2SiteCount = Properties.Settings.Default.WebToWV2.Cast<string>()
                    .Where(s => s.IndexOf(e.Address) >= 0).Count();
    
                if (wv2SiteCount > 0)
                {
                    WebViewInfo.Navigate(e.Address);
                    RequestChangeBrowser?.Invoke(null, new RequestChangeBrowserEventArgs(WebViewInfo.Browser));
                }
            }
        }
    
    1 回复  |  直到 1 月前
        1
  •  4
  •   Gabriel Luci    1 月前

    这是因为 await 作品什么时候 按计划行事 Task 返回 . 因此,您的程序是这样工作的:

    1. Main 跑步,打电话 Initializer.Start()
    2. 跑步和打电话 ChromiumInfo.InitializeAsync()
    3. 运行直到它调用 await Task.WhenAll(settingInit, browserSettingInit)
    4. 因为 Task.WhenAll 返回一个不完整的 任务 ChromiumInfo.InitializeAsync() 返回其自身的不完整项 任务 Initializer.Start() .
    5. 这个 等候 Initializer.Start() 看到不完整的 任务 并返回其自身的不完整 任务 Main() .
    6. 因为 Main() 不按计划行事 任务 Initializer.Start()

    async 和使用 等候

    public static async Task Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        await Initializer.Start();
    }
    

    创造能力 Main() a feature introduced in C# 7.1 .