创建一个从阻塞线程订阅事件的表单
Creating a form that subscribes to events from a blocking thread
所以我必须更新程序以使用更新版本的 Awesomium,特别是 1.7.5
有了更新,Awesomium 现在必须在它自己的线程上运行,而且它是阻塞的。
我可以使用 WebCore.QueueWork() 将工作排队到阻塞线程,这将完成在调用线程 WebCore.Run() 上传递的操作。我确保给它自己的线程,这样我的应用程序的其余部分就不会阻塞。
程序过去的运行方式是创建一个工作对象,该对象具有一个构造函数,该构造函数使用 WebCore 库实例化了 WebView 和 WebSession。然后它创建了一个表单,该表单接受一个工作对象作为参数,允许该表单订阅来自 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 线程正在阻塞,我无法使此表单在其上正常工作。
这就是我被困的地方。我需要 运行 表单在一个单独的线程中,这样它就不会挂起,因为它被阻塞的 WebCore 线程卡住了。
我的思路如下:
- 创建工作人员时,在新线程中创建一个表单作为工作人员实例的 属性。
- 当 WebCore 事件发生时,worker 实例应该能够更新它的表单。
它正在编译,表单是响应式的,但图片没有更新,我怀疑这与现在处于不同线程中的表单有关。这是我现在拥有的相关代码:
我把这个属性加到工人class:
public PBForm2 DebugForm;
我在 WebCore 阻塞线程中实例化 worker class:
WebCore.QueueWork(AddWorker);
在 AddWorker 方法中,我创建了一个新线程和 运行 一个 Form,同时将它附加到 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();
}
最后,工人事件本身现在是:
((ImageSurface)_view.Surface).Updated += (s, e) =>
{
ImageSurface buffer = (ImageSurface)_view.Surface;
DebugForm.pictureBox1.Image = buffer.Image;
DebugForm.pictureBox1.Refresh();
};
看起来非常接近工作,表单响应用户交互,工作人员正在做他们的事情并触发事件,但图片在表单中并没有改变。事件正在发生并且新图像在那里,我怀疑表单在不同的线程中导致表单上的图像不更新。
这篇文章很长 post 如果您正在阅读本文,感谢您抽出宝贵的时间来阅读所有内容。在线程方面,我是一个新手,非常感谢任何建议或链接,甚至是搜索什么来解决这个问题。
您正在创建 2 个相同的表单:
worker.DebugForm = new PBForm2(worker.Id);
var debugForm = new PBForm2(worker.Id);
然后加载 debugForm,但是您的更新是对 DebugForm.picturebox1 完成的,因此您的更新将不会被看到。需要对 debugForm.picturebox1 进行更新,但您应该只创建一个。
在看不到所有代码的情况下,为什么不直接将代码加载到工作程序中 class 或将一个指向另一个?
Application.Run(worker.DebugForm);
Application.DoEvents();
或
worker.DebugForm = new PBForm2(worker.Id);
var debugForm = worker.DebugForm;
Application.Run(debugForm);
Application.DoEvents();
我想通了,在解决了我更新错误的 Form 对象的问题后(感谢 Troy Mac1ure),我 运行 陷入了一个线程问题,我无法从 Awesomium 线程访问 Form 的图片框.
我用助手解决了它class:
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,特别是 1.7.5
有了更新,Awesomium 现在必须在它自己的线程上运行,而且它是阻塞的。
我可以使用 WebCore.QueueWork() 将工作排队到阻塞线程,这将完成在调用线程 WebCore.Run() 上传递的操作。我确保给它自己的线程,这样我的应用程序的其余部分就不会阻塞。
程序过去的运行方式是创建一个工作对象,该对象具有一个构造函数,该构造函数使用 WebCore 库实例化了 WebView 和 WebSession。然后它创建了一个表单,该表单接受一个工作对象作为参数,允许该表单订阅来自 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 线程正在阻塞,我无法使此表单在其上正常工作。
这就是我被困的地方。我需要 运行 表单在一个单独的线程中,这样它就不会挂起,因为它被阻塞的 WebCore 线程卡住了。
我的思路如下:
- 创建工作人员时,在新线程中创建一个表单作为工作人员实例的 属性。
- 当 WebCore 事件发生时,worker 实例应该能够更新它的表单。
它正在编译,表单是响应式的,但图片没有更新,我怀疑这与现在处于不同线程中的表单有关。这是我现在拥有的相关代码:
我把这个属性加到工人class:
public PBForm2 DebugForm;
我在 WebCore 阻塞线程中实例化 worker class:
WebCore.QueueWork(AddWorker);
在 AddWorker 方法中,我创建了一个新线程和 运行 一个 Form,同时将它附加到 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();
}
最后,工人事件本身现在是:
((ImageSurface)_view.Surface).Updated += (s, e) =>
{
ImageSurface buffer = (ImageSurface)_view.Surface;
DebugForm.pictureBox1.Image = buffer.Image;
DebugForm.pictureBox1.Refresh();
};
看起来非常接近工作,表单响应用户交互,工作人员正在做他们的事情并触发事件,但图片在表单中并没有改变。事件正在发生并且新图像在那里,我怀疑表单在不同的线程中导致表单上的图像不更新。
这篇文章很长 post 如果您正在阅读本文,感谢您抽出宝贵的时间来阅读所有内容。在线程方面,我是一个新手,非常感谢任何建议或链接,甚至是搜索什么来解决这个问题。
您正在创建 2 个相同的表单:
worker.DebugForm = new PBForm2(worker.Id);
var debugForm = new PBForm2(worker.Id);
然后加载 debugForm,但是您的更新是对 DebugForm.picturebox1 完成的,因此您的更新将不会被看到。需要对 debugForm.picturebox1 进行更新,但您应该只创建一个。
在看不到所有代码的情况下,为什么不直接将代码加载到工作程序中 class 或将一个指向另一个?
Application.Run(worker.DebugForm);
Application.DoEvents();
或
worker.DebugForm = new PBForm2(worker.Id);
var debugForm = worker.DebugForm;
Application.Run(debugForm);
Application.DoEvents();
我想通了,在解决了我更新错误的 Form 对象的问题后(感谢 Troy Mac1ure),我 运行 陷入了一个线程问题,我无法从 Awesomium 线程访问 Form 的图片框.
我用助手解决了它class:
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));