错误:使用CefSharp的Form.close()时“跨线程操作无效”

时间:2017-07-21 07:29:42

标签: c# chromium-embedded

我使用Cefsharp.Winform(http://cefsharp.github.io/)。 我尝试Form.Close()但它错误: System.InvalidOperationException:'跨线程操作无效:控制'Form2'从其创建的线程以外的线程访问。'

Form1.cs的

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TEST_CEF
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 frm2 = new Form2();
            frm2.Show();
        }
    }
}

Form2.cs

using CefSharp;
using CefSharp.WinForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TEST_CEF
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
            InitBrowser();

        }

        public ChromiumWebBrowser browser;
        public void InitBrowser()
        {
            Cef.Initialize(new CefSettings());
            browser = new ChromiumWebBrowser("www.google.com");
            this.Controls.Add(browser);
            browser.Dock = DockStyle.Fill;

            browser.FrameLoadEnd += WebBrowserFrameLoadEnded;
        }

        private void WebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
        {
            if (e.Frame.IsMain)
            {
                if (browser.Address.IndexOf("google") > -1)
                {
                    timer1.Start();
                }
            }
        }

        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            browser.Dispose();
            Cef.Shutdown();
        }
        int time = 0;
        private void timer1_Tick(object sender, EventArgs e)
        {
            time++;
            if (time==3)
            {
                this.Close();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您使用哪种计时器? 考虑在timer1_Tick方法中使用InvokeRequired。

private void timer1_Tick(object sender, EventArgs e)
{
    if (InvokeRequired) { Invoke(new Action(() => { timer1_Tick(sender, e); })); return; }

    time++;
    if (time==3)
    {
        this.Close();
    }
}

答案 1 :(得分:0)

来自docs(强调我):

  

值得注意的是,此事件是在CEF UI线程上触发的,该线程默认情况下与应用程序UI线程不同。阻止此线程持续任何时间是不明智的,因为您的浏览器将无响应和/或挂起.. 要访问UI元素,您需要调用/分发到UI线程。

所以你在另一个线程中启动计时器,所以我想在这个CEF UI线程中也会引发Tick事件。

因此,如果需要,您必须使用Invoke

Action close = () => this.Close();
if (InvokeRequired)
    Invoke(close);
else
    close();