HttpWebRequest.BeginGetRequestStream阻止UI线程

时间:2012-06-14 20:51:33

标签: c# .net httpwebrequest

首先,我对C#和.NET Framework一般都很陌生,但我想要实现的是(恕我直言)相当简单的目标,但我仍然遇到了一些麻烦。

我的目标是使用WebRequest类将数据发布到Web服务。我已经阅读了documentation和示例,特别是这一部分:

  

BeginGetRequestStream方法需要一些同步设置任务   完成(DNS解析,代理检测和TCP套接字   连接,例如)此方法变为异步之前。作为一个   结果,永远不应该在用户界面(UI)上调用此方法   线程,因为它可能需要一些时间,通常是几秒钟。

参考链接的示例,如何使方法GetRequestStreamCallbackGetResponseCallback在后​​台线程中运行?

这是我到目前为止所得到的:

private void startTask()
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
            worker.RunWorkerAsync();
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            updateStatus(e.ProgressPercentage);
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            postData = /* data to be posted */;
            byte[] postBytes = Encoding.UTF8.GetBytes(postData);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://example.com");
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = postBytes.Length;
            request.Method = "POST";

            request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
        }

        private void GetRequestStreamCallback(IAsyncResult result)
        {
            HttpWebRequest request = (HttpWebRequest)result.AsyncState;

            using (Stream stream = request.EndGetRequestStream(result))
            {
                stream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetBytes(postData).Length);
                stream.Close();
            }

            request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
        }

        private void GetResponseCallback(IAsyncResult result)
        {
            HttpWebRequest request = (HttpWebRequest)result.AsyncState;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
            Console.WriteLine(response.StatusDescription);
        }

我使用BackgroundWorker的原因是与UI进行交互,但我对其他解决方案持开放态度。我的问题是:当执行流程到达worker_DoWork函数的末尾时,工作者是否会终止?甚至回调函数都由工作人员自己执行?如果没有,是否有另一种方法可以使整个代码在一个单独的线程中运行?

我为(可能)愚蠢的问题道歉,但正如我所说,我是.NET的新手,我仍然没有掌握线程池和线程池的概念。

1 个答案:

答案 0 :(得分:2)

BackgroundWorker线程在DoWork函数结束时完成,然后在启动BackgroundWorker的线程上引发RunWorkerCompleted。

在您的示例中,GetResponseCallback将在不同的线程上运行,因为调用request.BeginGetRequestStream的线程将在DoWork结束时返回到池。

为简单起见,您可以使用同步版本或请求/响应方法(例如request.GetRequestStream),因为您不再位于UI线程上。您的UI线程可以侦听RunWorkedCompleted以从UI线程中获取调用结果。