Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在套接字类中使用数据接收事件?_C#_.net_Sockets_Winsockets - Fatal编程技术网

C# 如何在套接字类中使用数据接收事件?

C# 如何在套接字类中使用数据接收事件?,c#,.net,sockets,winsockets,C#,.net,Sockets,Winsockets,我已经编写了一个简单的客户端,它在dotnet中使用TcpClient进行通信。为了等待来自服务器的数据消息,我使用了一个Read()线程,该线程在套接字上使用阻塞Read()调用。当我收到一些东西时,我必须生成各种事件。这些事件发生在工作线程中,因此您无法直接从它更新UIInvoke()可以使用,但对于最终开发人员来说,这很困难,因为我的SDK可能会被根本不使用UI或使用表示框架的用户使用。表示框架有不同的处理方法调用()在我们的测试应用程序上作为Microstation插件目前需要花费大量时

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

我希望我的事件与UI在同一个线程中生成,这样用户就不必通过
Dispatcher
Invoke

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

我在
IOControl()
函数中找到了
IOControlCode.AsyncIO
标志,该函数的帮助说明

启用数据丢失时的通知 等待接收。此值为 等于Winsock 2
FIOASYNC
不变的


我找不到任何关于如何使用它获取通知的示例。如果我在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提供的。