当通过计时器进行呼叫时,WebBrowser控件不会导航到URL

时间:2014-09-10 17:17:41

标签: c# wpf multithreading timer webbrowser-control

我正在尝试使用集成的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成立,计时器被禁用,浏览器应该导航回主页,但没有任何反应......悲伤的故事:(

2 个答案:

答案 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);        
}