C# 如何在套接字类中使用数据接收事件?
我已经编写了一个简单的客户端,它在dotnet中使用TcpClient进行通信。为了等待来自服务器的数据消息,我使用了一个C# 如何在套接字类中使用数据接收事件?,c#,.net,sockets,winsockets,C#,.net,Sockets,Winsockets,我已经编写了一个简单的客户端,它在dotnet中使用TcpClient进行通信。为了等待来自服务器的数据消息,我使用了一个Read()线程,该线程在套接字上使用阻塞Read()调用。当我收到一些东西时,我必须生成各种事件。这些事件发生在工作线程中,因此您无法直接从它更新UIInvoke()可以使用,但对于最终开发人员来说,这很困难,因为我的SDK可能会被根本不使用UI或使用表示框架的用户使用。表示框架有不同的处理方法调用()在我们的测试应用程序上作为Microstation插件目前需要花费大量时
Read()
线程,该线程在套接字上使用阻塞Read()
调用。当我收到一些东西时,我必须生成各种事件。这些事件发生在工作线程中,因此您无法直接从它更新UIInvoke()
可以使用,但对于最终开发人员来说,这很困难,因为我的SDK可能会被根本不使用UI或使用表示框架的用户使用。表示框架有不同的处理方法<代码>调用()在我们的测试应用程序上作为Microstation插件目前需要花费大量时间。Microstation是单线程应用程序,其线程上的调用并不好,因为它总是忙于绘图和其他工作,消息处理时间太长
我希望我的事件与UI在同一个线程中生成,这样用户就不必通过Dispatcher
或Invoke
现在我想知道,当数据到达时,套接字如何通知我?是否有一个内置的回调。我喜欢winsock风格的接收事件,而不使用单独的读取线程。我也不想使用窗口计时器来轮询数据
我在IOControl()
函数中找到了IOControlCode.AsyncIO
标志,该函数的帮助说明
启用数据丢失时的通知
等待接收。此值为
等于Winsock 2FIOASYNC
不变的
我找不到任何关于如何使用它获取通知的示例。如果我在MFC/Winsock中是正确的,那么我们必须创建一个大小为
的窗口(0,0)
,该窗口仅用于侦听数据接收事件或其他套接字事件。但我不知道如何在dotnet应用程序中做到这一点。好的,我已经安装并运行了它。我真正想要的是如何将事件无缝地发布到UI线程,在该线程中创建连接。在阅读了框架代码之后,我提出了以下概念证明<代码>同步上下文可用于将我的组件绑定到创建它的UI线程。然后我可以直接将事件发布到该UI线程,而无需使用Invoke
在下面的示例中,我创建了一个ThreadUISafeTimer
,它使用一个单独的线程,就像我的socket客户端使用一个线程来读取和引发事件一样。在这种情况下,context
用于在不为null的情况下发布事件,否则使用工作线程引发事件
[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);
}
}
}
}
看一看这个问题,这个问题大致相同,通过使用事件代理模式解决 基本上,您将拥有一个对象,其中包含所有线程都订阅的事件。它还将具有一个可以调用的方法,该方法将调用事件。这听起来可能很复杂,但相当简单
示例代码如下。在linux中,它非常易于使用。但是仍然找不到在dotnet应用程序中使用
FIOASYNC
的示例。似乎我必须使用回调函数调用BeginReceive()
,在该回调中我再次调用BeginReceive()
。这是msdn提供的。