避免使用此选项.对c#compact框架中的事件处理程序调用(.)
本文关键字:事件处理 程序 调用 框架 c#compact 选项 | 更新日期: 2023-09-27 18:25:48
我使用了一个单独的类,该类根据机器类型实例化不同的条形码对象,一旦读取条形码,就会引发事件。
因此,为了将其传输到表单,我还引发了一个唯一的事件"myEvent",我的所有表单都会侦听该事件,但在表单内部,我必须使用它。Invoke((Action)mymethod(argument));能够在用户界面上更新组件,只要myEvent的处理程序在不同于表单的另一个线程上执行即可。
所以我有这个:
我的类->barbarcode.read(..)被触发,然后从它的处理程序I Raise myEvent(在我的窗体上捕获),以及从窗体上myEvent的处理程序,我执行this。调用…
我知道这是一个标准的过程,但我想去掉Invoke,而是直接调用myMethod(参数);作用
我认为这与确保类线程安全有关,但我不知道如何在我的情况下实现这一点。
事实上,如果我在表单中使用原始制造商barbarbarbarcode.readed()事件,它就不需要调用invoke,只要这是线程安全的,但我不知道如何模仿它,我真的需要将所有不同的条形码处理程序封装在不同的项目中,这样我的表单就只能使用一个返回所需条形码的"myEvent",从而不重复代码。
提前感谢
Roger Tranchez
如果从控件继承类(基本上是创建一个新的自定义控件),则可以在不使用Invokes的情况下处理UI线程上的事件,因为控件(条形码读取器类)是UI线程的一部分。
听起来像是在使用工作线程读取条形码,以保持UI的响应性。条形码对象只在创建它的线程上运行
您可以集中事件处理(以避免重复代码)并读取工作线程上的条形码,如下所示:
- 将条形码对象包装在公开MyEvent的自定义对象/库MyBarcodeReader中
- 在MyBarcodeReader的构造函数中,将当前SynchronizationContext捕获到类字段syncContext。如果表单构造MyBarcodeReader,这将是UI的SynchronizationContext
- 激活MyBarcodeReader(例如MyBarcodeReader.Execute)时,在工作线程上创建条形码对象
- 当您需要引发MyEvent时,调用syncContext.Send(这将在工作线程上),传递一个用于引发MyEvent的委托。syncContext.Send将同步到UI线程(如Control.Invoke)。下面的代码说明了这一点
public class MyBarcodeReader
{
private readonly SynchronizationContext syncContext;
// Handler for barcode object's Readed event.
private void Barcode.Readed(Object sender, Event e)
{
// Block the worker thread to synchronize with the thread associated
// with SynchronizationContext.
syncContext.Send(SyncMyEvent, (Object)e);
}
// Raises MyEvent on the thread associated with SynchronizationContext,
// usually a UI thread.
private void SyncMyEvent(Object o)
{
if (MyEvent != null)
{
MyEvent((Event)o);
}
}
// Constructor.
public MyBarcodeReader()
{
syncContext = SynchronizationContext.Current;
}
}
这里的方法将阻塞工作线程(与Control.Invoke相同),但不会阻塞UI线程。如果您有一个或多个订阅MyEvent的表单,则它们不需要使用Control.Invoke;他们甚至不需要知道worker线程。
SynchronizationContext上有一些优秀的在线参考资料,请参阅CodeProject和MSDN杂志。
我在这里找到了一个解决方案:基本上,它将表单控件传递给类构造函数,然后在该类中使用表单。Invoke从表单ui线程激发事件。
类别:
using System;
using System.Windows.Forms;
using System.Threading;
namespace ThreadTest
{
public class WorkerClass
{
private Thread thr;
// UI control for update
public Control UIControl { get; set; }
public delegate void StatusUpdate(DateTime dateTime, string message);
public event StatusUpdate OnStatusUpdate;
// Starts thread
public void Start()
{
thr = new Thread(new ThreadStart(MainWorker));
thr.Start();
}
// Main thread worker
public void MainWorker()
{
int i = 0;
while (true)
{
string message = string.Format("Value of i={0}", i++);
FireStatusUpdate(DateTime.Now, message);
Thread.Sleep(1000);
}
}
// Fire thread safe event
private void FireStatusUpdate(DateTime dateTime, string message)
{
// UIControl is set and OnStatusUpdate has subscriber
if (UIControl != null && OnStatusUpdate != null)
{
if (UIControl.InvokeRequired)
{
UIControl.Invoke(new StatusUpdate(FireStatusUpdate),
new object[] { dateTime, message });
return;
}
OnStatusUpdate(dateTime, message);
}
}
}
}
形式:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
WorkerClass worker = new WorkerClass();
// add event handler
worker.OnStatusUpdate += new WorkerClass.StatusUpdate(worker_OnStatusUpdate);
// add UI control to invoke
worker.UIControl = this;
worker.Start();
}
void worker_OnStatusUpdate(DateTime dateTime, string message)
{
label1.Text = dateTime.ToLongTimeString();
label1.Text += " " + message;
}
}
在我的案例中,我已经将事件类型从StatusUpdate更改为
EventHandler<MyEventArgs>
,是MyEventArgs此类:
public class MyEventArgs : EventArgs
{
public string MyString { get; set; }
}
谢谢!