我是 C# .Net 和 Visual Studio 2022 的新手 - 我想要实现的是每秒运行一个计时器来检查网站 url 是否有效/是否已启动。如果 url 可访问并且当前 WebView2 未显示该网站,那么它应该导航到该网站。如果它已经显示该网站,则它不应该执行任何其他操作。如果它显示该网站,但现在它不再有效,则 WebView 应导航到我的自定义错误页面。如果在自定义错误页面上网站再次可用,则应(重新)加载网站。
在我的特定场景中,我现在正在使 webView 加载 localhost (127.0.0.1)。我想不断检查网站的IP,如果它出现故障,则显示自定义错误,如果它回来,则显示该网站。
不确定我解释得很好。根据我所做的研究,我相信我需要 Task 并使用异步方法等待。
这是我当前的计时器和 checkurl 代码以及 navigtionstarted 和 navigationcompeted:
private void webView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
timerCheckRSLCDURL.Enabled = false;
}
private void webView_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)
{
if (e.IsSuccess)
{
Debug.WriteLine("JT:IsSuccess");
((Microsoft.Web.WebView2.WinForms.WebView2) sender).ExecuteScriptAsync("document.querySelector('body').style.overflow='hidden'");
}
else if (!e.IsSuccess)
{
Debug.WriteLine("JT:IsNOTSuccess");
webView.DefaultBackgroundColor = Color.Blue;
//webView.CoreWebView2.NavigateToString(Program.htmlString);
}
timerCheckRSLCDURL.Enabled = true;
}
private void timerCheckRSLCDURL_Tick(object sender, EventArgs e)
{
Debug.WriteLine("Timer Fired! Timer.Enabled = " + timerCheckRSLCDURL.Enabled);
CheckURL(Properties.Settings.Default.URL, Properties.Settings.Default.Port);
}
private async void CheckURL(string url, decimal port)
{
timerCheckRSLCDURL = false;
Program.isWebSiteUp = false;
string webViewURL = BuildURL();
Debug.WriteLine("Checking URL: " + webViewURL);
try
{
var request = WebRequest.Create(webViewURL);
request.Method = "HEAD";
var response = (HttpWebResponse) await Task.Factory.FromAsync < WebResponse > (request.BeginGetResponse, request.EndGetResponse, null);
if (response.StatusCode == HttpStatusCode.OK)
{
Program.isWebSiteUp = true;
}
}
catch (System.Net.WebException exception)
{
Debug.WriteLine("WebException: " + exception.Message);
if (exception.Message.Contains("(401) Unauthorized"))
{
Program.isWebSiteUp = false;
}
else
{
Program.isWebSiteUp = false;
} // This little block is unfinished atm as it doesn't really affect me right now
}
catch (Exception exception)
{
Debug.WriteLine("Exception: " + exception.Message);
Program.isWebSiteUp = false;
}
if (Program.isWebSiteUp == true && webView.Source.ToString().Equals("about:blank"))
{
Debug.WriteLine("JT:1");
Debug.WriteLine("isWebSiteUp = true, webView.Source = about:blank");
webView.CoreWebView2.Navigate(webViewURL);
}
else if (Program.isWebSiteUp == true && !webView.Source.ToString().Equals(webViewURL))
{
Debug.WriteLine("JT:2");
Debug.WriteLine("isWebSiteUp = true\nwebView.Source = " + webView.Source.ToString() + "\nwebViewURL = " + webViewURL + "\nWebView Source == webViewURL: " + webView.Source.ToString().Equals(webViewURL) + "\n");
webView.CoreWebView2.Navigate(webViewURL);
}
else if (Program.isWebSiteUp == false && !webView.Source.ToString().Equals("about:blank"))
{
Debug.WriteLine("JT:3");
Debug.WriteLine("This SHOULD be reloading the BSOD page!");
webView.CoreWebView2.NavigateToString(Program.htmlString);
}
}
private string BuildURL()
{
string webViewURL;
string stringURL = Properties.Settings.Default.URL;
string stringPort = Properties.Settings.Default.Port.ToString();
string stringURLPORT = $ "{stringURL}:{stringPort}";
if (stringPort.Equals("80"))
{
webViewURL = stringURL;
}
else
{
webViewURL = stringURLPORT;
}
if (!webViewURL.EndsWith("/"))
{
webViewURL += "/";
}
//For now, the URL will always be at root, so don't need to worry about accidentally
//making an invalid url like http://example.com/subfolder/:port
//although potentially will need to address this at a later stage
Debug.WriteLine("BuildURL returns: " + webViewURL);
return webViewURL;
}
因此计时器每 1000 毫秒(1 秒)触发一次,因为我需要主动检查 URL 是否仍然存在。我认为我控制计时器的方式是错误的 - 我想有更好的方法,但我想做的是......
- 每 1 秒检查一次网站 URL
- 为了避免重复相同的异步任务,我尝试禁用计时器,以便在异步 checkurl 运行时它不会再次触发
- 一旦检查 url 的 async/await 任务完成,应重新启用计时器以继续监视网站 url 是否仍然存在
- 如果网站关闭,它应该显示我的自定义错误页面(称为 BSOD),这是从资源加载并“存储”在 Program.htmlString 中的一些超级基本 html
- 如果网站关闭,并且 webview 已经显示 BSOD,则 webview 不应该执行任何操作。计时器应继续监视 URL。
- 如果网站已启动并且 Web 视图显示 BSOD,则它应该导航到已检查的已启动 URL。如果网站已启动,并且 Web 视图已显示该网站,则 Web 视图不应该执行任何操作。计时器应继续监视 URL。
从其他研究来看,我知道我不应该使用private async void
- 例如不应该将其用作空白。但我还没有弄清楚/理解正确的方法来做到这一点
在立即窗口中,看起来webView_NavigationCompleted
立即被触发两次(有时甚至几次),因为立即窗口输出将显示JT:IsSuccess
or JT:IsNOTSuccess
快速连续地重复几次。这正常吗?我假设那里有些东西不正确。
主要问题似乎是由于计时器只有 1 秒。例如,如果我将计时器更改为每 30 秒触发一次,它似乎可以正常工作,但是当每秒触发一次时(我什至可能在某些时候需要的时间少于该时间),它就无法真正按预期工作。例如,有时 BSOD 根本无法加载,webView_NavigationCompleted
快速连续多次起火等
有人可以帮助我使这段代码变得更好和正确吗?
我搜索了无数的网站等,虽然有一些很好的信息,但其中一些似乎势不可挡/可以说技术性太强。我必须先查一下“前因”的含义,因为它对我来说是一个全新的词! :捂脸:
提前谢谢了