C# 创建订阅来自阻塞线程的事件的窗体

C# 创建订阅来自阻塞线程的事件的窗体,c#,multithreading,winforms,events,awesomium,C#,Multithreading,Winforms,Events,Awesomium,因此,我必须更新一个程序以使用更新版本的Awesomium,特别是1.7.5 随着更新的进行,Awesomium现在必须在它自己的线程上运行,并且它正在阻塞 我可以使用WebCore.QueueWork()将工作排队到阻塞线程,这将完成在调用WebCore.Run()的线程上传递的操作。我确保给它自己的线程,这样我的应用程序的其余部分就不会阻塞 程序运行的方式是创建一个worker对象,该对象具有一个构造函数,该构造函数使用WebCore库实例化WebView和WebSession。然后,它创建

因此,我必须更新一个程序以使用更新版本的Awesomium,特别是1.7.5

随着更新的进行,Awesomium现在必须在它自己的线程上运行,并且它正在阻塞

我可以使用WebCore.QueueWork()将工作排队到阻塞线程,这将完成在调用WebCore.Run()的线程上传递的操作。我确保给它自己的线程,这样我的应用程序的其余部分就不会阻塞

程序运行的方式是创建一个worker对象,该对象具有一个构造函数,该构造函数使用WebCore库实例化WebView和WebSession。然后,它创建了一个表单,该表单接受一个worker对象作为参数,该参数允许表单订阅WebCore库中的事件

var worker = new Worker();
var debugForm = new PBForm(worker);
debugForm.Show();
辅助构造函数有一行代码,每当更新视图时,它都会调用函数SurfaceIsDirty

((ImageSurface)_view.Surface).Updated += (s, e) => { if (webView_SurfaceIsDirty != null) webView_SurfaceIsDirty(s, e); };
此函数在窗体构造函数中分配:

this.worker.webView_SurfaceIsDirty = (sender, e) =>
{
    ImageSurface buffer = (ImageSurface)this.worker._view.Surface;
    pictureBox1.Image = buffer.Image;
};
因此,每当WebView更新时,表单图片都会更新

((ImageSurface)_view.Surface).Updated += (s, e) => { if (webView_SurfaceIsDirty != null) webView_SurfaceIsDirty(s, e); };
这过去可以在WebCore线程中运行,但现在由于WebCore线程被阻塞,我无法使此表单在其上正常工作

这就是我被困的地方。我需要在一个单独的线程中运行表单,这样它就不会因为被WebCore线程阻塞而挂起

我的想法如下:

  • 创建辅助对象时,在新线程中创建一个窗体作为辅助对象实例的属性
  • 当WebCore事件发生时,worker实例应该能够更新其表单
  • 它正在编译,表单是响应的,但是图片没有更新,我怀疑这与表单现在处于不同的线程中有关。以下是我目前掌握的相关代码:

    我已将此属性添加到worker类:

    public PBForm2 DebugForm;
    
    我在WebCore阻塞线程中实例化worker类:

    WebCore.QueueWork(AddWorker);
    
    在AddWorker方法中,我创建一个新线程并运行一个窗体,同时将其附加到worker属性:

    static void AddWorker()
    {
        var worker = new Worker();
        Workers.Add(worker);
        new Thread(() =>
        {
            worker.DebugForm = new PBForm2(worker.Id);
            var debugForm = new PBForm2(worker.Id);
    
            Application.Run(debugForm);
            Application.DoEvents();
    
        }).Start();
    }
    
    最后,worker事件本身现在是:

    ((ImageSurface)_view.Surface).Updated += (s, e) =>
    {
        ImageSurface buffer = (ImageSurface)_view.Surface;
        DebugForm.pictureBox1.Image = buffer.Image;
        DebugForm.pictureBox1.Refresh();
    };
    
    它似乎非常接近于工作,表单响应用户交互,工作人员正在做他们的事情并触发事件,但是表单中的图片没有改变。事件被命中并且新的图像在那里,我怀疑表单位于不同的线程中这一事实导致表单上的图像无法更新


    这是一篇很长的文章,所以如果你正在阅读这篇文章,感谢你花时间来完成这一切。对于线程,我是一个新手,任何建议或链接,甚至搜索什么来解决这个问题,我都将不胜感激。

    您正在创建两个相同的表单:

    worker.DebugForm = new PBForm2(worker.Id);
    var debugForm = new PBForm2(worker.Id);
    
    然后加载debugForm,但正在对debugForm.picturebox1进行更新,因此不会看到您的更新。需要对debugForm.picturebox1进行更新,但您应该只创建一个

    在没有看到所有代码的情况下,为什么不直接加载worker类中的一个或将一个指向另一个

    Application.Run(worker.DebugForm);
    Application.DoEvents();
    


    我找到了答案,在解决了更新错误表单对象的问题后(感谢Troy Mac1ure),我遇到了一个线程问题,无法从Awesomium线程访问表单的picturebox

    我用一个助手类解决了这个问题:

    public static class ThreadHelper
    {
        private delegate void SetPictureCallback(PBForm f, Image image);
        private delegate void AppendTextCallback(PBForm f, string text);
    
        public static void SetPicture(PBForm form, Image image)
        {
            if (form.InvokeRequired)
            {
                SetPictureCallback d = SetPicture;
                form.Invoke(d, form, image);
            }
            else
            {
                form.pictureBox1.Image = image;
                form.pictureBox1.Refresh();
            }
        }
    
        public static void AppendText(PBForm form, string text)
        {
            if (form.InvokeRequired)
            {
                AppendTextCallback d = AppendText;
                form.Invoke(d, form, text);
            }
            else
            {
                form.textBox1.Text += text;
                form.textBox1.SelectionStart = form.textBox1.TextLength - 1;
                form.textBox1.ScrollToCaret();
                form.textBox1.ScrollToCaret();
            }
        }
    }
    
    在工作线程中触发事件时,我调用函数更新表单:

    _view.Surface = new ImageSurface();
    ((ImageSurface)_view.Surface).Updated += (s, e) =>
    {
        ImageSurface buffer = (ImageSurface)_view.Surface;
        ThreadHelper.SetPicture(DebugForm, buffer.Image);
        Application.DoEvents();
    };
    
    _view.ConsoleMessage += (s, e) =>
        ThreadHelper.AppendText(DebugForm, string.Format("{0} : {1} [{2}]\r\n", e.LineNumber, e.Message, e.Source));
    

    这解决了一个问题,但导致了另一个问题,我无法从触发事件的Awesomium线程访问表单的pictureBox1。我通过创建一个调用Form.Invoke函数的静态类来正确调用对表单的更改,从而使其正常工作。