0

I use Cefsharp.Winform (http://cefsharp.github.io/). I Try Form.Close() but it error: System.InvalidOperationException: 'Cross-thread operation not valid: Control 'Form2' accessed from a thread other than the thread it was created on.'

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 Answers2

0

Which kind of timer do you use? Consider using InvokeRequired in the timer1_Tick method.

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

    time++;
    if (time==3)
    {
        this.Close();
    }
}
Janos
  • 165
  • 10
0

From the docs (emphasis from me):

It's important to note this event is fired on a CEF UI thread, which by default is not the same as your application UI thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang.. To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.

So you start the timer in another thread so I suppose the Tick event will be raised in this CEF UI thread, too.

So you must use Invoke if needed:

Action close = () => this.Close();
if (InvokeRequired)
    Invoke(close);
else
    close();
György Kőszeg
  • 17,093
  • 6
  • 37
  • 65