如何在Socket类中使用数据接收事件?

我写了一个简单的客户端,在dotnet中使用TcpClient进行通信。 为了等待来自服务器的数据消息,我使用一个在socket上使用阻塞Read()调用的Read()线程。 当我收到的东西,我必须生成各种事件。 这些事件发生在工作线程中,因此您无法直接从其更新UI。 Invoke()可以使用,但对于最终开发人员来说很困难,因为我的SDK可能会被完全不使用UI或使用Presentation Framework的用户使用。 演示框架有不同的处理方式。 在我们的测试应用程序上Invoke() ,因为Microstation Addin需要花费大量时间。 Microstation是单线程应用程序,并且其线程上的调用调用并不好,因为它总是忙于绘图和其他东西消息需要很长时间才能处理。

我希望我的事件在与UI相同的线程中生成,因此用户不必通过DispatcherInvoke

现在我想知道当数据到达时如何通过套接字通知我? 是否有一个内置的回调。 我喜欢winsock样式接收事件而不使用单独的读取线程。 我也不想使用窗口计时器来轮询数据。

我在IOControl()函数中找到了IOControlCode.AsyncIO标志

启用等待接收数据的通知。 该值等于Winsock 2 FIOASYNC常量。

我找不到任何关于如何使用它来获取通知的示例。 如果我在MFC / Winsock中是正确的,我们必须创建一个size(0,0)的窗口,该窗口仅用于监听数据接收事件或其他套接字事件。 但我不知道如何在dotnet应用程序中这样做。

好的,我把它弄好了。 我真正想要的是如何将事件无缝地发布到UI线程,在该线程中创建了我的连接。 在完成框架代码之后,我想出了以下概念certificate。 SynchronizationContext可用于将我的组件绑定到创建它的UI线程。 然后我可以直接将事件发布到该UI线程,而无需使用Invoke

在下面的示例中,我创建了一个ThreadUISafeTimer ,它使用一个单独的线程,就像我的socket客户端一样,用于读取和引发事件。 在这种情况下,如果不为null,则使用context来发布事件,否则使用worker线程引发事件。

 [DefaultEvent("Tick")] public class ThreadUISafeTimer : Component { private const int True = 1; private const int False = 0; private int enabled = False; private SynchronizationContext context; public event EventHandler Tick = delegate { }; [DefaultValue(false)] public ushort Interval { get; set; } public ThreadUISafeTimer() { Interval = 100; this.Events.AddHandler("Tick", Tick); //If this class is created by a UI thread it will always post the Tick event to it. //otherwise it would be null and Tick would occur in a seperate thread. context = SynchronizationContext.Current; } protected override bool CanRaiseEvents { get { return true; } } [DefaultValue(false)] public bool Enabled { get { return enabled == True; } set { int newval = value ? True : False; if (enabled != newval) { if (newval == False) Thread.VolatileWrite(ref enabled, False); else { enabled = True; ThreadPool.QueueUserWorkItem( new WaitCallback(delegate(object o) { try { do { try { Thread.Sleep(Interval); if (Thread.VolatileRead(ref enabled) == True) { var callback = new SendOrPostCallback(delegate(object arg) { try { Tick(this, EventArgs.Empty); } catch (Exception exp) { Application.OnThreadException(exp); return; } }); //If context is null raise Tick event from current thread if (context == null) callback(null); else //otherwise post it to the UI thread that owns this timer. context.Post(callback, null); } } catch (ThreadInterruptedException) { } } while (Thread.VolatileRead(ref enabled) == True); } catch (ThreadAbortException) { } }), null); } } } } 

看看这个大致相同的问题,并使用Event Broker模式解决。

向正在等待TCP的线程发送指令?

基本上你会有一个对象,其中包含所有线程订阅的事件。 它还将有一个可以调用的方法来调用该事件。 这可能听起来很复杂,但相当简单。

示例代码在此处http://msforge.net/blogs/paki/archive/2007/11/20/EventBroker-implementation-in-C_2300_-full-source-code.aspx 。