订阅的Singleton方法未触发-嵌套的Windows窗体
将对新移动设备的支持添加到旧版应用程序。
基于本文实现的单例类
Create Event on Singleton Class
public sealed class Singleton
{
static readonly Singleton instance=new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
创建时,每个表单都将本地方法预订为条形码对象的读取方法
singleton.Instance.scanEngine.BarcodeRead += new BarcodeReadEventHandler(FormA_BarcodeReadMethod);
关闭时,每个表单都取消订阅条形码对象的读取方法
singleton.Instance.scanEngine.BarcodeRead-=新的BarcodeReadEventHandler(FormA_BarcodeReadMethod);
场景#1
从主菜单表单调用
''singleton.Instance.scanEngine.BarcodeRead + = new BarcodeReadEventHandler(FormA_BarcodeReadMethod);'
BarcodeReader.BarcodeScan事件singleton.Instance.scanEngine.BarcodeRead-= new BarcodeReadEventHandler(FormA_BarcodeReadMethod);
从主屏幕中调用的其他5种形式如上所述也可以正常运行
在某些情况下,具有扫描仪订阅的表单会调用另一种也需要扫描仪订阅的表单
场景2:
从主菜单窗体调用
singleton.Instance.scanEngine.BarcodeRead + =新的BarcodeReadEventHandler(FormB_BarcodeReadMethod);
处理触发事件时,FormB如下调用FormC
singleton.Instance.scanEngine.BarcodeRead-=新的BarcodeReadEventHandler(FormB_BarcodeReadMethod);
singleton.Instance.scanEngine.BarcodeRead + =新的BarcodeReadEventHandler(FormC_BarcodeReadMethod);
singleton.Instance.scanEngine.BarcodeRead-=新的BarcodeReadEventHandler(FormC_BarcodeReadMethod);
singleton BarcodeReader.BarcodeScan事件为null;
-控件返回到FormB
-FormB事件订阅单例BarcodeReader.BarcodeScan事件ingleton.Instance.scanEngine.BarcodeRead + = new BarcodeReadEventHandler(FormB_BarcodeReadMethod);
-Singleton BarcodeReader.BarcodeScan事件不为null;
-条形码扫描和FormB_BarcodeReadMethod触发。
预期的结果是,已订阅的FormC事件将触发,但不会触发,我不知道为什么会这样。
任何帮助,不胜感激。
对评论1的回应
在FormB中,决定调用FormC
在FormB扫描仪上的事件已取消订阅
clsApplicationController.Instance.scanEngineIntermec.BarcodeRead -= new
BarcodeReadEventHandler(this.frmB_Intermec_OnRead);
this.Update();
Application.DoEvents();
FormC的调用如下
using (formC _formC = new formC())
{
_formC.cUser = _cUser;
var _result = _formC.ShowDialog();
if (_result != DialogResult.OK) return;
}
事件在FormC构造函数中订阅
clsApplicationController.Instance.scanEngine.BarcodeRead += new
BarcodeReadEventHandler(this.frmC_OnRead);
this.Update();
Application.DoEvents();
对评论2的回应
订阅但未触发的FormC事件
void formC_OnRead(object sender, BarcodeReadEventArgs bre)
{
try {
ProcessScan(bre.strDataBuffer, sender);
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
formC_OnRead方法已预订到FormC构造函数中的Instance.scanEngineIntermec.BarcodeRead事件。
ProcessScan是通用的,可用于所有扫描仪类型。
在工作表格上采用相同的方法和方法
最佳答案
我通常喜欢对条形码进行抽象处理,以使整个应用程序不依赖于供应商SDK,从而在需要时可以更轻松地移植应用程序。我将跳过该切线的详细信息,但是这种方法还可以简化整个应用程序中的条形码处理。
保持您的条形码管理器单例,并让他成为唯一接触条形码SDK对象的实体。让您的表单或其他对象通过调用单例条形码管理器来注册接收条形码通知的兴趣,并将其维护在堆栈中,以便将条形码通知路由到最顶层的监听器。因此,在您有一个处理条形码的窗体A调用一个也处理对话框的对话框B的情况下,您不必进行任何微管理。显示表单或对话框时,它将在“加载”或“激活”中调用BarcodeManager.Instance.PushBarcodeListener(this)
。当它关闭或停用时,您可以调用BarcodeManager.Instance.PopBarcodeListener(this)
。如果您始终使用它,Barcodemanager将知道当前/顶级监听器是谁,并仅通知该对象。
监听器本身是一个独立于SDK的接口(interface),任何想要接收条形码事件的对象都可以实现。让我们将其称为IBarcodeListener,并将定义一种方法,该方法传递条形码就绪数据:
void HandleBarcode(BarcodeReadEventArgs evt);
(您甚至可以支持遍历监听器的遍历,在该遍历中,事件会在堆栈中冒泡,直到被处理为止,但现在让我们保持其简单性)。
在您的条形码管理器单例中:
private void PushBarcodeListener(IBarcodeListener l)
{
m_listeners.Push(l);
if (m_listeners.Count == 1)
{
// as soon as you have an interested party, add your one and only
// event handler to the SDK object and enable it (the exact details
// of this are SDK dependent).
}
}
private void PopBarcodeListener(IBarcodeListener l)
{
if (!Object.ReferenceEquals(l, m_listeners.Peek())
Throw new Exception("Only the active BarcodeListener can be removed");
m_listeners.Pop();
if (m_listeners.Count == 0)
{
// if no one is interested in barcodes, stop listening by disabling the SDK
// object and removing the event handler
}
}
当然,在一个唯一的SDK事件处理程序中,您将这样通知顶级监听器:
if (m_listeners.Count != 0)
m_listeners.Peek().HandleBarcode(evt)
免责声明,此代码未经过语法检查,我只是从内存中执行此操作。您将需要纠正错别字。
有关此添加内容的上下文,请参见注释。
这是一些我在UI线程“异步”上运行代码的代码示例。请注意,如果从UI线程调用,则它基本上在消息泵处理完所有当前Windows消息后运行:
public System.IAsyncResult BeginInvoke(System.Delegate method)
{
return base.MainForm.BeginInvoke(method);
}
public System.IAsyncResult BeginInvoke(System.Delegate method, params object[] args)
{
return base.MainForm.BeginInvoke(method, args);
}
请注意,“MainForm”是对应用程序中根表单的引用,并且此代码位于我的“应用对象”中,该对象是整个应用程序的根对象,因此可以在任何地方访问。
关于c# - 订阅的Singleton类事件未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57768151/