【问题标题】:How to stop synchronous request to server in c#?如何在 C# 中停止对服务器的同步请求?
【发布时间】:2014-10-17 05:18:29
【问题描述】:

我知道以前有人问过这个问题,但我的情况不同。因为我不知道下面的代码是做什么的。我只是将它用作第三方开源工具。

我正在使用开源工具“UnityHTTP”从服务器获取响应。 如果需要很长时间,我想取消响应请求。

我不是 C# 专家,所以我无法理解该工具提供的代码中发生了什么。

如果有人可以在这里帮助我,我将不胜感激。

获取响应的代码如下

    private void GetResponse() {
        System.Diagnostics.Stopwatch curcall = new System.Diagnostics.Stopwatch();
        curcall.Start();
        try {

            var retry = 0;
            while (++retry < maximumRetryCount) {
                if (useCache) {
                    string etag = "";
                    if (etags.TryGetValue (uri.AbsoluteUri, out etag)) {
                        SetHeader ("If-None-Match", etag);
                    }
                }

                SetHeader ("Host", uri.Host);

                var client = new TcpClient ();
                client.Connect (uri.Host, uri.Port);
                using (var stream = client.GetStream ()) {
                    var ostream = stream as Stream;
                    if (uri.Scheme.ToLower() == "https") {
                        ostream = new SslStream (stream, false, new RemoteCertificateValidationCallback (ValidateServerCertificate));
                        try {
                            var ssl = ostream as SslStream;
                            ssl.AuthenticateAsClient (uri.Host);
                        } catch (Exception e) {
                            Debug.LogError ("Exception: " + e.Message);
                            return;
                        }
                    }
                    WriteToStream (ostream);
                    response = new Response ();
                    response.request = this;
                    state = RequestState.Reading;
                    response.ReadFromStream(ostream);
                }
                client.Close ();

                switch (response.status) {
                case 307:
                case 302:
                case 301:
                    uri = new Uri (response.GetHeader ("Location"));
                    continue;
                default:
                    retry = maximumRetryCount;
                    break;
                }
            }
            if (useCache) {
                string etag = response.GetHeader ("etag");
                if (etag.Length > 0)
                    etags[uri.AbsoluteUri] = etag;
            }

        } catch (Exception e) {
            Console.WriteLine ("Unhandled Exception, aborting request.");
            Console.WriteLine (e);
            exception = e;
            response = null;
        }
        state = RequestState.Done;
        isDone = true;
        responseTime = curcall.ElapsedMilliseconds;

        if ( completedCallback != null )
        {
            if (synchronous) {
                completedCallback(this);
            } else {
                // we have to use this dispatcher to avoid executing the callback inside this worker thread
                ResponseCallbackDispatcher.Singleton.requests.Enqueue( this );
            }
        }

        if ( LogAllRequests )
        {
#if !UNITY_EDITOR
            System.Console.WriteLine("NET: " + InfoString( VerboseLogging ));
#else
            if ( response != null && response.status >= 200 && response.status < 300 )
            {
                Debug.Log( InfoString( VerboseLogging ) );
            }
            else if ( response != null && response.status >= 400 )
            {
                Debug.LogError( InfoString( VerboseLogging ) );
            }
            else
            {
                Debug.LogWarning( InfoString( VerboseLogging ) );
            }
#endif
        }           
    }

我可以看出它与 以下行:-

 System.Diagnostics.Stopwatch curcall = new System.Diagnostics.Stopwatch();
        curcall.Start(); 

【问题讨论】:

    标签: c# .net unity3d


    【解决方案1】:

    正在使用TcpClient 类发出请求。它有两个属性ReceiveTimeoutSendTimeout。初始化TcpClient 后,在建立连接之前为这两个属性设置所需的值:

    var client = new TcpClient ();
    client.ReceiveTimeout = 2000; // 2 seconds
    client.SendTimeout = 2000;    // 2 seconds
    

    这样做会导致 TcpClient 在超时后自动取消请求。

    仅供参考 - 以下仅用于衡量请求花费的时间。

     System.Diagnostics.Stopwatch curcall = new System.Diagnostics.Stopwatch();
     curcall.Start(); 
     ...
     responseTime = curcall.ElapsedMilliseconds;
    

    【讨论】:

    • 那是否意味着总超时时间为 4 秒,(发送 + 接收)?
    • 在上面的例子中,是的,TcpClient 等待的最大总时间为 4 秒。 TcpClient 客户端类中没有单个超时设置,因为发送和接收被视为两个离散操作。
    • 另外我应该提一下 client.Connect(host, port) 不会尊重这些超时值,所以如果这里发生了长时间的等待,代码仍然会阻塞。如果你想实现一个超时连接,看看这两个例子:stackoverflow.com/questions/17118632/…splinter.com.au/opening-a-tcp-connection-in-c-with-a-custom-t
    • 好吧.. 如这些答案中所述,我必须使用我无法使用的异步请求,因为在我的情况下,当与服务器通信时,代码的执行必须冻结。这就是我使用同步请求的原因。
    • 其实这不是真的。异步请求只是意味着主线程有能力在另一个线程上发出请求时做其他事情。如果您阅读了这两个答案中提供的解决方案,他们正在发出异步请求,但随后利用他们的能力做其他事情以创建计时器机制来计算自发出请求以来已经过了多长时间。如果请求长于阈值,则终止请求线程,否则返回连接。这使它们同步,因此适合您的需求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多