获取 EventHandler 以在原始线程上调用 Invoke()
Get EventHandler to call Invoke() on original thread
我正在使用 System.Threading.Timer
异步重复某个任务。当任务准备就绪时,应执行原始线程(调用 Start()
的地方)上的方法。
public event EventHandler StatusChanged;
public void Start()
{
StatusChanged += new EventHandler(SomethingChangedMethod);
new Timer(Pending, null, 0, 1000);
}
private void Pending(object state)
{
//Do Something
StatusChanged?.Invoke(this, EventArgs.Empty);
}
因为我不在控件上什么的,所以我不能调用Invoke()
或BeginInvoke()
。
首先,您可能无法 post 向调用 Start
的线程发送消息:您只能在线程具有消息队列的情况下执行此操作与之关联,并正在检查该队列。 UI 个线程执行此操作,但是例如线程池线程或您使用 new Thread()
创建的线程不会。
如果线程有与之关联的消息队列,通常的做法是在该线程上安装 SynchronizationContext
。您可以使用 SynchronizationContext.Current
获取线程的 SynchronizationContext
,将其存储起来,然后使用 SynchronizationContext
将 post 消息发送到该线程的消息队列。如果线程没有安装 SynchronizationContext
,SynchronizationContext.Current
returns null
.
public event EventHandler StatusChanged;
private Timer timer;
private SynchronizationContext synchronizationContext;
public void Start()
{
synchronizationContext = SynchronizationContext.Current;
StatusChanged += new EventHandler(SomethingChangedMethod);
timer = new Timer(Pending, null, 0, 1000);
}
private void Pending(object state)
{
// Do Something
if (synchronizationContext != null)
{
synchronizationContext.Post(_ => StatusChanged?.Invoke(this, EventArgs.Empty), null);
}
else
{
StatusChanged?.Invoke(this, EventArgs.Empty);
}
}
Since Start() can be called from outside the library I have no real control about that.
作为图书馆作者,您不知道什么是正确的做法。众所周知,原来的线程刚刚开始调用 Start
并在很久以前就退出了。你不知道回到“同一个”“线程”是正确的行为,所以当然,是的,你把它留给你的消费者。
以同样的方式,作为一个库作者,你不应该固定选择使用什么日志框架,是否以及如何向用户显示错误消息(如果有用户的话)等。
做简单的事情,发起你的活动,让为应用程序挑选框架的人做出正确的选择。因为你不应该(不一定会损害图书馆的潜在消费者)
我正在使用 System.Threading.Timer
异步重复某个任务。当任务准备就绪时,应执行原始线程(调用 Start()
的地方)上的方法。
public event EventHandler StatusChanged;
public void Start()
{
StatusChanged += new EventHandler(SomethingChangedMethod);
new Timer(Pending, null, 0, 1000);
}
private void Pending(object state)
{
//Do Something
StatusChanged?.Invoke(this, EventArgs.Empty);
}
因为我不在控件上什么的,所以我不能调用Invoke()
或BeginInvoke()
。
首先,您可能无法 post 向调用 Start
的线程发送消息:您只能在线程具有消息队列的情况下执行此操作与之关联,并正在检查该队列。 UI 个线程执行此操作,但是例如线程池线程或您使用 new Thread()
创建的线程不会。
如果线程有与之关联的消息队列,通常的做法是在该线程上安装 SynchronizationContext
。您可以使用 SynchronizationContext.Current
获取线程的 SynchronizationContext
,将其存储起来,然后使用 SynchronizationContext
将 post 消息发送到该线程的消息队列。如果线程没有安装 SynchronizationContext
,SynchronizationContext.Current
returns null
.
public event EventHandler StatusChanged;
private Timer timer;
private SynchronizationContext synchronizationContext;
public void Start()
{
synchronizationContext = SynchronizationContext.Current;
StatusChanged += new EventHandler(SomethingChangedMethod);
timer = new Timer(Pending, null, 0, 1000);
}
private void Pending(object state)
{
// Do Something
if (synchronizationContext != null)
{
synchronizationContext.Post(_ => StatusChanged?.Invoke(this, EventArgs.Empty), null);
}
else
{
StatusChanged?.Invoke(this, EventArgs.Empty);
}
}
Since Start() can be called from outside the library I have no real control about that.
作为图书馆作者,您不知道什么是正确的做法。众所周知,原来的线程刚刚开始调用 Start
并在很久以前就退出了。你不知道回到“同一个”“线程”是正确的行为,所以当然,是的,你把它留给你的消费者。
以同样的方式,作为一个库作者,你不应该固定选择使用什么日志框架,是否以及如何向用户显示错误消息(如果有用户的话)等。
做简单的事情,发起你的活动,让为应用程序挑选框架的人做出正确的选择。因为你不应该(不一定会损害图书馆的潜在消费者)