创建一个订阅来自阻塞线程

时间:2017-07-07 21:15:22

标签: c# multithreading winforms events awesomium

所以我必须更新程序才能使用更新版本的Awesomium,特别是1.7.5

随着更新,Awesomium现在必须对其自己的线程进行操作,并且它已经阻止。

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

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

var worker = new Worker();
var debugForm = new PBForm(worker);
debugForm.Show();

worker构造函数有这行代码,每当视图更新时都会调用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更新,表单图片就会更新。

这曾经能够在WebCore线程中运行,但现在由于WebCore线程阻塞,我无法使此表单在其上正常工作。

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

我的想法如下:

  1. 创建worker时,在新线程中创建一个表单作为worker实例的属性。
  2. 当WebCore事件发生时,工作者实例应该能够更新它的表格。
  3. 它正在编译,表单是响应式的,但图片没有更新,我怀疑它现在与表单处于不同的线程有关。这是我现在的相关代码:

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

    public PBForm2 DebugForm;
    

    我在WebCore阻塞线程中实例化了worker类:​​

    WebCore.QueueWork(AddWorker);
    

    在AddWorker方法中,我创建一个新线程并在将其附加到worker属性时运行Form:

    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();
    }
    

    最后工人事件本身就是:

    ((ImageSurface)_view.Surface).Updated += (s, e) =>
    {
        ImageSurface buffer = (ImageSurface)_view.Surface;
        DebugForm.pictureBox1.Image = buffer.Image;
        DebugForm.pictureBox1.Refresh();
    };
    

    它似乎非常接近工作,表单响应用户交互,工作人员正在做他们的事情并触发事件,但图片在表单中没有变化。事件被点击并且新图像在那里,我怀疑表单在不同的线程中导致表单上的图像不更新。

    这是一个非常长的帖子,所以如果你正在阅读这个感谢你花时间来完成这一切。我非常喜欢线程和任何建议或链接,甚至是搜索解决这个问题的具体内容都将非常感激。

2 个答案:

答案 0 :(得分:2)

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

worker.DebugForm = new PBForm2(worker.Id);
var debugForm = new PBForm2(worker.Id);

然后加载debugForm,但是您的更新正在对DebugForm.picturebox1进行更新,因此您的更新将不会被看到。需要对debugForm.picturebox1进行更新,但是您应该只创建一个。

在没有看到所有代码的情况下,为什么不在工作者类中加载一个代码或者将一个代码指向另一个代码呢?

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

worker.DebugForm = new PBForm2(worker.Id);
var debugForm = worker.DebugForm;

Application.Run(debugForm);
Application.DoEvents();

答案 1 :(得分:1)

我弄明白了,在解决了我更新错误的Form对象的问题后(​​感谢Troy Mac1ure)我遇到了一个线程问题,我无法从Awesomium线程访问Form的图片框。

我使用帮助程序类解决了它:

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));
相关问题