【问题标题】:C# Async Socket Client Blocks Main Interface ThreadC# 异步套接字客户端阻塞主接口线程
【发布时间】:2012-04-23 14:42:41
【问题描述】:

这次的另一个网络问题与至少在这个初始版本中基于 MSDN 示例的异步套接字客户端有关。当前,当用户单击界面上的按钮时,会尝试 Async Connect 以连接到联网设备,代码如下所示 -

//Mouse Event handler for main thread
private void btn_Read_MouseDown(object sender, MouseEventArgs e)
{
    Stopwatch sw = Stopwatch.StartNew();
    if (!networkDev.Connected)
        networkDev.Connect("192.168.1.176", 1025);

    if(networkDev.Connected)
       networkDev.getReading();
    sw.Stop();//Time time taken...
}

如果端点已打开并存在于网络上,则此代码可以正常工作(整个操作不到一秒)。但是,如果联网设备被关闭或不可用,AsyncSocket Connect 函数会阻止主窗体线程。目前,如果设备不可用,整个界面会锁定大约 20 秒(使用秒表)。我认为我正在锁定,因为主线程正在等待连接请求的返回,这是否意味着我需要将该连接请求放在另一个线程上?

我已经包含了我正在使用的异步套接字客户端的代码 -

    public bool Connect(String ip_address, UInt16 port)
    {
        bool success = false;

        try
        {
            IPAddress ip;
            success = IPAddress.TryParse(ip_address, out ip);
            if (success)
                success = Connect(ip, port);
        }
        catch (Exception ex)
        {
            Console.Out.WriteLine(ex.Message);
        }
        return success;
    }     

    public bool Connect(IPAddress ip_address, UInt16 port)
    {
        mSocket.BeginConnect(ip_address, port, 
           new AsyncCallback(ConnectCallback), mSocket);
        connectDone.WaitOne();//Blocks until the connect operation completes, 
                              //(time taken?) timeout?
        return mSocket.Connected;
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        //Retreive the socket from thestate object
        try
        {
            Socket mSocket = (Socket)ar.AsyncState;
            //Set signal for Connect done so that thread will come out of 
            //WaitOne state and continue
            connectDone.Set();

        }
        catch (Exception ex)
        {
            Console.Out.WriteLine(ex.Message);
        }       
    }

我希望通过使用具有自己线程的异步客户端,如果主机不存在,这将停止冻结接口,但情况似乎并非如此。在 20 秒的初始连接失败后,所有后续连接尝试都会立即返回(不到一毫秒)。还有一点我觉得很奇怪,如果初始连接尝试成功,以后任何连接到不存在的主机的调用都会立即返回。对正在发生的事情感到有些困惑,但想知道这是否与我使用的 Socket 存储在我的 AsyncSocket 类中这一事实有关。非常感谢任何帮助,如果需要更多客户端代码,请告诉我。

【问题讨论】:

  • 您在 WaitOne 旁边的评论中看到“阻塞直到操作完成”?究竟是异步的,你认为它阻塞了哪个线程。
  • 我现在已经把它拿出来了,因为这是事后看来,冻结界面的问题显而易见。这解决了最初问题的接口问题,尽管如果 Connect 无法完成,我似乎无法再次使用该套接字,并且当断开连接可能相对频繁地发生时,这是一个问题。每个 AsyncClient 都绑定到 1 个 Socket,允许重新连接的最佳方式是什么?目前我只是得到异常说线程正在等待上一个开始连接。任何关于更好解决方案的建议都表示赞赏。

标签: c# sockets networking asynchronous timeout


【解决方案1】:

您声称它是异步的,但您的 Connect 方法显然不是:

mSocket.BeginConnect(ip_address, port, ...);
connectDone.WaitOne(); // Blocks until the connect operation completes [...]

你一直阻塞直到它完成,这是异步行为的对立面。如果您要在连接之前阻塞,那么使用BeginConnect 有什么意义?

【讨论】:

  • 嗯,我使用 MSDN 示例作为我的代码的基础,所以我无法理解他们为什么将 WaitOne 放入连接中?我希望这个例子 (msdn.microsoft.com/en-us/library/bbx2eya8.aspx) 会是一个不错的起点。看来我错了!如果我按下按钮几次,如果没有等待,它会提出许多异常,说明在另一个操作正在进行时无法连接。无论如何,是否可以更快地使其他连接尝试超时,以便在不稳定的环境中可以更频繁地进行重新连接尝试?
  • @jackocurly0074:我无法看到任何连接超时属性,不……但您可能应该确保您不要尝试建立多个并发连接。
【解决方案2】:

你在这里阻塞了你的 UI 线程:

connectDone.WaitOne();  //Blocks until the connect operation completes, (time taken?) timeout?

【讨论】:

  • 你们回复速度很快,谢谢!取出 WaitOne 会阻止界面冻结,但会产生另一个问题。这发生在随后的连接尝试中-> System.dll 中发生的“System.InvalidOperationException”类型的第一次机会异常无法在同一套接字上进行另一个异步操作时调用 BeginConnect。问题是,一旦套接字连接失败,我就无法再次使用它,并且对于相关运行时的其余部分似乎无法使用?
猜你喜欢
  • 1970-01-01
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
相关资源
最近更新 更多