0

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

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

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

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

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

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

4

2 回答 2

1

好的,我启动并运行了。我真正想要的是如何将事件无缝地发布到创建我的连接的 UI 线程。在浏览了框架代码之后,我提出了以下概念证明。SynchronizationContext可用于将我的组件绑定到创建它的 UI 线程。然后我可以直接将事件发布到该 UI 线程,而无需使用Invoke.

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

[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);
                }
            }
        }
    }
于 2011-01-05T21:00:15.717 回答
0

看看这个大致相同的问题,并通过使用事件代理模式解决。

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

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

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

于 2011-01-05T21:13:01.633 回答