我有一个带有Socket的类,监听客户端以接收数据。当我接收新数据时,我想调用一个事件(如果已实现),但是你知道每个连接都有自己的线程,所以事件将在该线程运行,你知道其余的。你不能使用表单控件。 如何调用事件(或调用它)。我是线程和网络编程的新手,所以我很欣赏任何一个例子。
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)
}
}
谢谢。
答案 0 :(得分:1)
如果要从非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();
}
}
答案 1 :(得分:0)
我遇到了上周我正在处理的Silverlight应用程序的类似问题,并使用了Dispatcher.BeginInvoke方法。使用Windows窗体,看起来可能更容易使用Control.BeginInvoke(尽管我认为两者都应该有效):http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx
答案 2 :(得分:0)
您可以使用典型的marshling操作(如Invoke
或BeginInvoke
)将委托的执行注入UI线程。只需将ISynchronizeInvoke
或SynchronizationContext
的实例传递给您的班级,以便进行整理。
但是,在你的情况下,我不会这样做。因为,无论如何,这些回调都是因为套接字事件而发生的,所以可能可能会变得艰难而沉重。你绝对不想用你所有的活动来抨击你的UI线程。相反,将所有相关数据打包并放入一个集合,然后UI线程可以在更合理的时间间隔内使用System.Windows.Forms.Timer
进行轮询。
我一直在抨击这些严厉的行动。他们被高估和过度使用。请记住,有两种在UI和工作线程之间共享数据和信令的通用方法。
Invoke
或BeginInvoke
推送方法System.Windows.Forms.Timer
拉取方法拉方法可以,而且往往更优雅。
答案 3 :(得分:0)
UI线程是一个UI问题。在我看来,你不应该担心在这段代码中调用ui线程。相反,事件的消费者应该执行Invoke
或他们碰巧需要做的任何其他线程。这样,如果UI用户需要更改其策略(例如,通过使用计时器),您的非UI相关代码将不需要更改。