避免使用此选项.对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

避免使用此选项.对c#compact框架中的事件处理程序调用(.)

如果从控件继承类(基本上是创建一个新的自定义控件),则可以在不使用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; }
}

谢谢!