C# 网络浏览器控制赢得';当通过计时器调用时,t导航到URL
我正在尝试用C#制作一个集成应用程序。我需要实现一些定期检查用户活动的功能,如果用户在一段时间内没有活动,它会将浏览器控件重定向回主页 下面是我的应用程序的代码片段。我正在使用该类定期调用C# 网络浏览器控制赢得';当通过计时器调用时,t导航到URL,c#,wpf,multithreading,timer,webbrowser-control,C#,Wpf,Multithreading,Timer,Webbrowser Control,我正在尝试用C#制作一个集成应用程序。我需要实现一些定期检查用户活动的功能,如果用户在一段时间内没有活动,它会将浏览器控件重定向回主页 下面是我的应用程序的代码片段。我正在使用该类定期调用CheckUserActivity方法,该方法只计算时间跨度,如果时间跨度大于某个阈值,它应该通过调用goHome方法重定向浏览器 不幸的是,这根本不起作用,而且这种行为对我来说相当奇怪。我添加了一些日志以查看实际发生的情况(见下文)。“应该马上离开”消息显示正常,但之后浏览器不会导航到主页,调用导航后的第二条
CheckUserActivity
方法,该方法只计算时间跨度,如果时间跨度大于某个阈值,它应该通过调用goHome
方法重定向浏览器
不幸的是,这根本不起作用,而且这种行为对我来说相当奇怪。我添加了一些日志以查看实际发生的情况(见下文)。“应该马上离开”消息显示正常,但之后浏览器不会导航到主页,调用导航后的第二条消息也不会显示
我绝对没有错误。除了对webBrowser的Navigate
方法的调用和之后的调用不知怎么消失之外,一切都正常工作。
我怀疑这个问题可能与线程有关,但我对C#的经验很少,所以我完全不知道这里可能存在什么问题
我还尝试使用System.Threading.Tasks.Task
库重写代码,方法与http://stackoverflow.com/questions/8267298/how-to-start-a-long-running-process-in-a-separate-thread
(sry用于代码块内的链接-信誉不足:D)。我将检查代码放入无限循环中,该循环作为长时间运行的任务运行,线程休眠两秒钟,但我遇到了完全相同的问题
非常感谢你的建议。下面是我的代码片段(它应该作为一个独立的项目工作):
XAML:
<Window x:Class="TimerTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="800" Width="800">
<Grid>
<WebBrowser x:Name="webBrowser"
LoadCompleted="webBrowser_LoadCompleted"
></WebBrowser>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TimerTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Uri URI_home;
private Timer timer;
private Uri URI_last;
private DateTime lastUsed;
public MainWindow()
{
URI_home = new Uri("http://example.com/", UriKind.RelativeOrAbsolute);
URI_last = URI_home;
InitializeComponent();
webBrowser.Navigate(URI_home);
// Create a timer with a two second interval.
timer = new Timer(2000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += CheckUserActivity;
timer.AutoReset = true;
timer.Enabled = false;
lastUsed = DateTime.Now;
}
private void goHome()
{
//System.Windows.Forms.MethodInvoker update = delegate()
//{
webBrowser.Navigate(URI_home);
//};
//webBrowser.invoke(update);
}
private void logMessage(string msg)
{
DateTime now = DateTime.Now;
Console.WriteLine(now.ToString() + ": " + msg);
}
private void CheckUserActivity(Object source, ElapsedEventArgs e)
{
logMessage("Entered CheckUserActivity handler");
DateTime now = DateTime.Now;
TimeSpan timeSpan = now - lastUsed;
logMessage("Timespan is " + timeSpan.Seconds.ToString());
if (timeSpan.Seconds > 5 && URI_home != URI_last)
{
timer.Enabled = false;
logMessage("Timer is now disabled.");
logMessage("Will go away soon.");
goHome();
logMessage("Should have gone home");
}
}
private void webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
WebBrowser browser = (WebBrowser)sender;
Uri URI_navigated = e.Uri;
URI_last = URI_navigated;
logMessage("WebBrowser LoadCompleted event triggered. LoadCompleted for URI (saved as URI_last): " + URI_navigated.AbsoluteUri);
logMessage("Timer enabled status: " + timer.Enabled.ToString());
lastUsed = DateTime.Now;
timer.Enabled = true;
logMessage("Timer is now enabled (end of LoadCompleted handler).");
}
}
}
浏览器启动后会导航到主页(example.com)。计时器已禁用,但在LoadCompleted
处理程序结束时启用。用户逗留了一会儿,然后单击页面上的链接<代码>加载完成
被触发(计时器保持启用状态,因为我们还不必更改URL)。用户再次逗留,但这次不在主页上,条件在里面
CheckUserActivity
在一段时间后为真,计时器被禁用,浏览器应该导航回主页,但什么也没有发生。。。悲伤的故事:(我怀疑您的计时器事件没有绑定到正确的计时器事件。
试试看
timer.Tick += CheckUserActivity;
编辑
可能是线程访问的问题:
private void goHome()
{
MethodInvoker update = delegate()
{
webBrowser.Navigate(URI_home);
};
webBrowser.invoke(update);
}
这是一个线程问题——如果用下面的方法替换goHome方法,它就会开始工作 享受:)
你有关于线程或其他东西的异常吗?@T00rk根本没有异常或错误。不要盲目地每2秒就把这些调用堆积起来;仅在
文档完成后触发它们
事件@TaW你能详细说明一下吗?我怀疑你从来没有让它完成过任何事情。就像一个用户不停地点击链接,从而阻塞了整个浏览器。在DocumentCompleted
事件中启动计时器,并在Elasped
事件中停止计时器。-(旁白:在某些情况下,使用两个计时器是有充分理由的,例如,一个用来启动,一个用来检测超时。)我使用的是System.Timers.Timer,它没有Tick属性。他写道,他使用的是'System.Timers.Timer',它没有通常的Tick
!事件您确定事件已触发吗?@T00rk是的。我看到了我设置的第一个消息框,但没有看到调用浏览器的导航方法后的消息框。当使用此消息框时,我得到“System.Windows.Controls.WebBrowser”不包含“invoke”的定义,并且找不到接受“System.Windows.Controls.WebBrowser”类型的第一个参数的扩展方法“invoke”(您是否缺少using指令或程序集引用?
在编译过程中…非常感谢!我有一种预感,它可能与线程有关,因为我在Java中遇到了类似的问题,但我不知道WPF中线程调度是如何工作的,所以我不确定如何修复它。
private void goHome()
{
MethodInvoker update = delegate()
{
webBrowser.Navigate(URI_home);
};
webBrowser.invoke(update);
}
private void goHome()
{
Dispatcher.InvokeAsync(() => { webBrowser.Navigate(URI_home); });
}