中止套接字操作Windows Phone

时间:2012-08-05 03:36:02

标签: sockets asynchronous windows-phone-7.1

我在Windows Phone 7应用程序中使用伪同步套接字。我的套接字代码基于http://msdn.microsoft.com/en-us/library/hh202858(v=vs.92).aspx的样本。

服务器的发送模式有些不可预测。它以固定大小的头开始,包含消息其余部分的长度。我首先阅读此标题,然后从套接字读取指定的字节数。

由于我还需要向服务器发送消息,并且我尝试使用线程进行双工接收以及另一个发送线程导致许多问题,我的代码中有一个这样的循环:

while (KeepConnectionGoing)
        {
            byte[] Rcvd;
            Rcvd = Socket.Receive();//Returns null if no message received in 50 ms
            if (Rcvd != null)
            {
                ParseMessage(Rcvd);
            }

            if (HasMessageThatNeedsToBeSent())
            {
                byte[] Message = GetMessageToSend();
                Socket.Send(Message);
            }
        }

这在大多数情况下都可以正常工作,但是当消息为空时会发生奇怪的事情。 因为Receive方法中的超时(请参阅链接的示例)使用ManualResetEvent,所以套接字上的接收请求实际上永远不会取消。即使该方法返回,该请求也会在某处等待,并且当套接字上的数据可用时,会清除标头。事件处理程序与它收到的数据无关(因为方法已经返回并且方法中的变量永远不会再次使用),数据基本上消失了。我期望返回标头跳过的读取请求读取标头之后的字节,我不知道消息有多长。

如果套接字超时,我希望能够取消所有未完成的请求。我正在使用像示例中的匿名方法,因为它简化了所有内容并阻止我自己编写所有状态转移代码。因此,我无法解开事件处理程序。我认为,即使我使用方法作为事件处理程序,但在异步操作完成之前取消挂钩,仍然会调用回调方法。 (我没有测试过,这只是我的理解)

现在,我能看到的唯一解决方案是将一些静态字节数组合在一起(即有一个静态byte [] Header,如果它为null,我会读取标题,否则我会读取该消息),但似乎就像一个非常不优雅的解决方案,非常容易出现竞争条件。

有更好的方法吗?

由于

1 个答案:

答案 0 :(得分:0)

似乎没有好办法做到这一点。 poll方法会很好,但Silverlight没有它。我使用静态标志一起破解了一个解决方案,告诉我我所处的状态(是否已请求标头,是否已请求消息),长度为静态int和静态缓冲区。

在方法开始时,可​​以请求标题或正文。如果已经请求了标头,则线程将等待直到有效的主体长度可用。如果此等待超时,则表示标头接收操作仍处于暂挂状态,但实际上没有可用消息。否则,它会读取消息的长度。

如果尚未请求标头,则接收标头。在事件处理程序中,完成后,检查控制流是否已经继续(即接收操作花费的时间太长,因此函数已经返回,但现在实际已完成)。更新长度,然后请求身体,除非它超时。

相关问题