我正在尝试使用集成的System.Windows.Controls.WebBrowser在C#中创建应用。我需要实现一些定期检查用户活动的功能,如果用户在某个时间段内没有活动,它会将浏览器控件重定向回主页。
以下是我的应用中的代码段。我正在使用System.Timers.Timer类定期调用CheckUserActivity
方法,该方法只计算时间跨度,如果时间跨度大于某个阈值,则应通过调用goHome
方法重定向浏览器。
不幸的是,这不会起作用,这种行为对我来说似乎很奇怪。我添加了一些日志记录来查看实际发生的情况(见下文)。 “即将离开”消息显示确定,但之后浏览器不会导航到主页,并且在调用Navigate
后第二条消息也没有显示。
我绝对没有错误。一切都按预期工作,除了调用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>
C#:
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).");
}
}
}
以下是一个会话的输出:
11.9.2014 8:10:01: WebBrowser LoadCompleted event triggered. LoadCompleted for URI (saved as URI_last): http://example.com/
11.9.2014 8:10:01: Timer enabled status: False
11.9.2014 8:10:01: Timer is now enabled (end of LoadCompleted handler).
11.9.2014 8:10:03: Entered CheckUserActivity handler
11.9.2014 8:10:03: Timespan is 2
11.9.2014 8:10:05: Entered CheckUserActivity handler
11.9.2014 8:10:05: Timespan is 4
11.9.2014 8:10:07: Entered CheckUserActivity handler
11.9.2014 8:10:07: Timespan is 6
11.9.2014 8:10:09: Entered CheckUserActivity handler
11.9.2014 8:10:09: Timespan is 8
11.9.2014 8:10:11: Entered CheckUserActivity handler
11.9.2014 8:10:11: Timespan is 10
11.9.2014 8:10:13: Entered CheckUserActivity handler
11.9.2014 8:10:13: Timespan is 12
11.9.2014 8:10:15: Entered CheckUserActivity handler
11.9.2014 8:10:15: Timespan is 14
11.9.2014 8:10:17: Entered CheckUserActivity handler
11.9.2014 8:10:17: Timespan is 16
11.9.2014 8:10:19: Entered CheckUserActivity handler
11.9.2014 8:10:19: Timespan is 18
11.9.2014 8:10:21: Entered CheckUserActivity handler
11.9.2014 8:10:21: Timespan is 20
11.9.2014 8:10:23: Entered CheckUserActivity handler
11.9.2014 8:10:23: Timespan is 22
11.9.2014 8:10:25: Entered CheckUserActivity handler
11.9.2014 8:10:25: Timespan is 24
11.9.2014 8:10:27: Entered CheckUserActivity handler
11.9.2014 8:10:27: Timespan is 26
11.9.2014 8:10:29: Entered CheckUserActivity handler
11.9.2014 8:10:29: Timespan is 28
11.9.2014 8:10:30: WebBrowser LoadCompleted event triggered. LoadCompleted for URI (saved as URI_last): http://www.iana.org/domains/reserved
11.9.2014 8:10:30: Timer enabled status: True
11.9.2014 8:10:30: Timer is now enabled (end of LoadCompleted handler).
11.9.2014 8:10:31: Entered CheckUserActivity handler
11.9.2014 8:10:31: Timespan is 1
11.9.2014 8:10:33: Entered CheckUserActivity handler
11.9.2014 8:10:33: Timespan is 3
11.9.2014 8:10:35: Entered CheckUserActivity handler
11.9.2014 8:10:35: Timespan is 5
11.9.2014 8:10:37: Entered CheckUserActivity handler
11.9.2014 8:10:37: Timespan is 7
11.9.2014 8:10:37: Timer is now disabled.
11.9.2014 8:10:37: Will go away soon.
浏览器启动后导航到主页(example.com)。计时器已禁用,但在LoadCompleted
处理程序结束时启用。用户稍微徘徊,然后单击页面上的链接。触发LoadCompleted
(计时器保持启用状态,因为我们不必更改URL)。用户再次徘徊,但这次不在主页上,条件在里面
一段时间后,CheckUserActivity
成立,计时器被禁用,浏览器应该导航回主页,但没有任何反应......悲伤的故事:(
答案 0 :(得分:1)
这是一个线程问题 - 如果你用下面的方法替换goHome方法,它就会开始工作。
享受:)
private void goHome()
{
Dispatcher.InvokeAsync(() => { webBrowser.Navigate(URI_home); });
}
答案 1 :(得分:0)
我怀疑你的计时器事件没有绑定到正确的事件。 试试这个
timer.Tick += CheckUserActivity;
修改强>
可能是线程访问问题:
private void goHome()
{
MethodInvoker update = delegate()
{
webBrowser.Navigate(URI_home);
};
webBrowser.invoke(update);
}