C# 创建订阅来自阻塞线程的事件的窗体
因此,我必须更新一个程序以使用更新版本的Awesomium,特别是1.7.5 随着更新的进行,Awesomium现在必须在它自己的线程上运行,并且它正在阻塞 我可以使用WebCore.QueueWork()将工作排队到阻塞线程,这将完成在调用WebCore.Run()的线程上传递的操作。我确保给它自己的线程,这样我的应用程序的其余部分就不会阻塞 程序运行的方式是创建一个worker对象,该对象具有一个构造函数,该构造函数使用WebCore库实例化WebView和WebSession。然后,它创建了一个表单,该表单接受一个worker对象作为参数,该参数允许表单订阅WebCore库中的事件C# 创建订阅来自阻塞线程的事件的窗体,c#,multithreading,winforms,events,awesomium,C#,Multithreading,Winforms,Events,Awesomium,因此,我必须更新一个程序以使用更新版本的Awesomium,特别是1.7.5 随着更新的进行,Awesomium现在必须在它自己的线程上运行,并且它正在阻塞 我可以使用WebCore.QueueWork()将工作排队到阻塞线程,这将完成在调用WebCore.Run()的线程上传递的操作。我确保给它自己的线程,这样我的应用程序的其余部分就不会阻塞 程序运行的方式是创建一个worker对象,该对象具有一个构造函数,该构造函数使用WebCore库实例化WebView和WebSession。然后,它创建
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线程阻塞而挂起
我的想法如下:
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函数的静态类来正确调用对表单的更改,从而使其正常工作。