TCP*_*W01 0 c# async-await cefsharp
我有一个方法可以进行 Chromium 浏览器初始化。运行两个异步方法后,程序自动关闭。难道是我用Task.WhenAll错了?
这是程序的入口点:
开始.cs
static class Start
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Initializer.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
初始化程序.cs
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());
}
}
Run Code Online (Sandbox Code Playgroud)
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为await工作原理。await当作用于不完整的 a时Task,它返回。所以你的程序是这样工作的:
Main运行并调用Initializer.Start()Initializer.Start()运行和调用ChromiumInfo.InitializeAsync()ChromiumInfo.InitializeAsync()运行直到调用await Task.WhenAll(settingInit, browserSettingInit)Task.WhenAll返回一个不完整的Task,ChromiumInfo.InitializeAsync()返回它自己的不完整Task并且执行返回到Initializer.Start()。await它自己的不完整并且执行返回到。Initializer.Start()TaskTaskMain()Main()不作用于Task返回的Initializer.Start(),所以执行继续到下一行,即程序的结尾。解决方案非常简单:将Main方法更改为async并使用await.
public static async Task Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
await Initializer.Start();
}
Run Code Online (Sandbox Code Playgroud)
make 的能力Main() async是C# 7.1 中引入的一项功能。
| 归档时间: |
|
| 查看次数: |
577 次 |
| 最近记录: |