tha*_*alm 2 .net c# events multithreading
主要问题是,从一个线程引发事件可以调用仅在某个线程上下文中调用的委托.在对这个问题进行一些研究后,我想,也许它可以传递某种同步上下文以及每个订阅事件:
SomeClass.SmartSyncEvent += (myDelegate, someReferenceToAThread);
Run Code Online (Sandbox Code Playgroud)
然后提出事件,它以某种方式:
foreach(subscriber)
{
someReferenceToAThread.Invoke(myDelegate);
}
Run Code Online (Sandbox Code Playgroud)
这是超伪代码,但也许有人已经做过这样的事情,或者知道任何可以设置这种模式的.NET类.谢谢!
执行此操作的最佳方法是通过SomeClass同步上下文ISynchronizeInvoke.
public class SomeClass
{
public event EventHandler SmartSyncEvent;
public ISynchronizeInvoke SynchronizingObject { get; set; }
public void RaiseSmartSyncEvent()
{
if (SynchronizingObject != null)
{
SynchronizingObject.Invoke(
(Action)(()=>
{
SmartSyncEvent();
}), null);
}
else
{
SmartSyncEvent();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种模式类似于实现的方式System.Timers.Timer.它的问题是每个用户将被编组到同一个同步对象上.看起来这不是你想要的.
幸运的是,委托存储了应该通过Target属性调用方法的类实例.我们可以通过提取它,我们调用委托前,并用它作为利用此的同步对象假设,当然,这是一个ISynchronizeInvoke本身.我们实际上可以通过使用自定义添加和删除事件访问器来强制执行.
public class SomeClass
{
private EventHandler _SmartSyncEvent;
public event EventHandler SmartSyncEvent
{
add
{
if (!(value.Target is ISynchronizeInvoke))
{
throw new ArgumentException();
}
_SmartSyncEvent = (EventHandler)Delegate.Combine(_SmartSyncEvent, value);
}
remove
{
_SmartSyncEvent = (EventHandler)Delegate.Remove(_SmartSyncEvent, value);
}
}
public void RaiseMyEvent()
{
foreach (EventHandler handler in _SmartSyncEvent.GetInvocationList())
{
var capture = handler;
var synchronizingObject = (ISynchronizeInvoke)handler.Target;
synchronizingObject.Invoke(
(Action)(() =>
{
capture(this, new EventArgs());
}), null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样做要好得多,因为每个用户可以独立于其他用户进行编组.它的问题是处理程序必须是驻留在ISynchronizeInvoke类中的实例方法.此外,Delegate.Target静态方法为null.这就是我使用自定义add访问器强制执行该约束的原因.
如果Delegate.Target为null,则可以使其同步执行处理程序,否则无法将其转换为有用的同步对象.这个主题有很多变化.
在WPF中,您可以代码DispatcherObject而不是代码ISynchronizeInvoke.
| 归档时间: |
|
| 查看次数: |
1263 次 |
| 最近记录: |