我目前正在使用多个动态加载的插件来开发模块化应用程序。主窗口还可以作为各种插件的反馈消息的输出。这是一个中心要求,因此插件无法拥有自己的输出。
主程序由3个类组成:
创建GUI并处理插件调用的主类
使用MEF从指定文件夹中收集插件的第二类
可从插件访问的导出类,以发送消息(字符串[])以显示在主窗口中
Export类使用一个事件来接收消息,主类订阅该事件并将消息写入DataGridView。
只要我启动插件而不将其放入单独的线程中,此方法就可以正常工作。但是正如预期的那样,插件运行时,主窗体被冻结了。现在,我尝试为插件创建单独的线程,以便可以在后台同时运行多个线程。不幸的是,这使消息接收到跨线程操作。
通过使用事件,我打算使其成为线程安全的,因为主表单订阅了该事件并处理“主线程”中的消息。显然我错了……我还是不太明白主窗口中的事件触发方法是如何突然切换到单独的任务中的...
一些其他信息:
调用不是一种选择,因为输出窗口不仅包含DataGridView,还包含更多控件,并且每当收到消息时,这些控件就会不断地被修改。
主要形式具有公共静态字符串[],用于将消息的内容从导出类传送到主要类
有什么方法可以将消息编写方法放入主线程,但仍然可以预订从另一个线程触发的事件?也许还有另一种方法可以完成这项任务?
[Export]
public class Exportklasse : Interfaces.IMain
{
public static event EventHandler MeldungEintragen;
// Diese Methode aufrufen, um von Modulen aus Textmeldungen einzutragen
public void MeldungEmpfangen(string[] MeldungInput, EventArgs e)
{
EventHandler EintragenEvent = MeldungEintragen;
if (EintragenEvent != null) {
MainForm.MeldungText = MeldungInput;
EintragenEvent(this, e);
}
}
}
类似这项工作吗?:
private readonly IBackendWorker worker;
private SynchronizationContext uiContext;
public MainForm(IBackendWorker worker)
{
InitializeComponent();
this.worker = worker;
uiContext = SynchronizationContext.Current;
worker.BackendEvent += OnWorkerBackEvent;
...
}
和事件处理程序:
private void OnWorkerBackEvent(int count)
{
// schedule the action on the UI synchronisation context.
uiContext.Post((c) =>
{
// put your code to interact with UI here
outputTextBox.Text = count.ToString();
}, null);
// or: uiContext.Post((c) => outputTextBox.Text = c.ToString(), count);
}
事件处理程序在触发事件的任何线程中执行,但在UI线程中执行操作。