我试图将遍历事件委托的订阅者列表所需的代码包装到静态帮助程序中,这样我就不需要为许多事件处理程序复制/粘贴相同的代码。我仍在学习 C# 的来龙去脉,而且我在细节上磕磕绊绊。
帮助程序将遍历事件订阅者列表并单独调用每个订阅者,以便订阅者的线程可以自动同步。许多事件将从 GUI 中的各种表单订阅,因此无需在每个表单类中管理事件的线程同步。
下面的代码显示了该概念的一个示例。最后一行....
singleCast.Invoke(paramList);
...由于几个原因,显然是无效的。
如何在不使用我理解的非常慢的 DynamicInvoke 方法的情况下调用每个订阅者?
有没有办法传入类型引用,以便 ForEach 返回特定事件 Delegates 与泛型 Delegates ?
请参见下面的示例代码:
namespace Reflection_Diagnostics
{
// ***********************
// *** Event Delegates ***
// ***********************
public delegate void SystemPoll();
public delegate void SystemStart(int option);
public delegate void SystemEnd();
class clsTestEvents
{
// **************
// *** Events ***
// **************
public event SystemPoll Event_SystemPoll;
public event SystemStart Event_SystemStart;
public event SystemEnd Event_SystemEnd;
// ***********************
// *** Event Overrides ***
// ***********************
private void OnEvent_SystemPoll() // Event Override
{
MyToolBox.SyncEvents(Event_SystemPoll);
}
private void OnEvent_SystemStart(int option) // Event Override
{
MyToolBox.SyncEvents(Event_SystemStart, option);
}
private void OnEvent_SystemEnd() // Event Override
{
MyToolBox.SyncEvents(Event_SystemEnd);
}
// ***********************
// *** Test The Events ***
// ***********************
public void TestTheEvents()
{
Event_SystemPoll();
Event_SystemStart(1);
Event_SystemEnd();
}
}
public class MyToolBox
{
// *******************
// *** Sync Events ***
// *******************
// Iterate through the event subscriber list and synchronize to the subscriber thread when needed
static public void SyncEvents(Delegate handler, params object[] paramList)
{
if (null != handler)
{
foreach (Delegate singleCast in handler.GetInvocationList())
{
ISynchronizeInvoke syncInvoke = singleCast.Target as ISynchronizeInvoke;
try
{
if ((syncInvoke != null) && (syncInvoke.InvokeRequired))
{
syncInvoke.Invoke(singleCast, paramList); // Subscriber is on a different thread
}
else
{
// Error: System.Delegate does not contain a definition for 'Invoke'.....
// singleCast is a generic Delegate, and so cannot be directly invoked.
// DynamicInvoke is avialable, but is much, MUCH, MUCH!! slower to execute
singleCast.Invoke(paramList); // Subscriber is on the same thread
}
}
catch
{
}
}
}
}
}
}