调用在 C# 中的其他线程上实现的事件
本文关键字:实现 事件 线程 其他 调用 | 更新日期: 2023-09-27 18:30:49
我有一个带有套接字的类,侦听客户端接收数据。当接收新数据时,我想调用一个事件(如果实现),但如您所知,每个连接都有自己的线程,因此事件将在该线程上运行,而您知道其余的。 不能使用窗体控件。 如何调用事件(或调用它)。我对线程和网络编程真的很陌生,所以我很欣赏任何例子。
public class HVremotechooser
{
public delegate void NewOrder(Order order);
public event NewOrder nOrder;
//... (code elided)
public void ReceiveCallback(IAsyncResult AsyncCall) // new connection of client
{
//... (code elided)
if (nOrder != null)
nOrder(Order); // calling the event "nOrder"
//... (code elided)
}
}
谢谢。
如果要从非 UI 线程更新窗体,则必须调用该操作。我通常做的是:
private void LongRunningBackgroundThread() {
// lots of work
...
// Update my form
InvokeIfRequired(() => {
...update form...
}
}
private static void InvokeIfRequired(Action a) {
if (control.InvokeRequired) {
control.Invoke(a);
} else {
a();
}
}
看这里和这里
上周处理的Silverlight应用程序中遇到了类似的问题,并使用了Dispatcher.BeginInvoke方法。 对于Windows表单,看起来使用Control.BeginInvoke可能更容易(尽管我相信两者都应该有效 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx):
典型的封送处理操作(如 Invoke
或 BeginInvoke
)将委托的执行注入到 UI 线程上。 只需将 ISynchronizeInvoke
或 SynchronizationContext
的实例传递给您的类即可简化封送处理。
但是,在您的情况下,我不会这样做。由于无论如何,这些回调可能是由于套接字事件而发生的,因此它们很可能是硬而重的。您绝对不想用所有这些活动猛击您的 UI 线程。相反,应打包所有相关数据并放入集合中,然后 UI 线程可以轮询该集合以更合理的间隔使用System.Windows.Forms.Timer
。
我一直在撕毁这些沼泽作业。它们被高估和过度使用。请记住,有两种常规方法可以在 UI 和工作线程之间共享数据和发出信号。
- 通过工作线程中的
Invoke
或BeginInvoke
推送方法 - 通过 UI 线程中的
System.Windows.Forms.Timer
拉取方法
拉动方法可以而且通常更优雅。
线程是一个 UI 问题。 在我看来,您不必担心在此代码中调用 ui 线程。 相反,事件的使用者应该做Invoke
或他们碰巧需要做的任何其他线程操作。这样,如果 UI 人员需要更改他们的策略(例如,通过使用计时器),您的非 UI 相关代码就不需要更改。