首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有BeginGetRequestStream/EndGetRequestStream的TaskFactory.FromAsync挂起

带有BeginGetRequestStream/EndGetRequestStream的TaskFactory.FromAsync挂起
EN

Stack Overflow用户
提问于 2012-12-31 14:25:55
回答 1查看 7.3K关注 0票数 4

我有一个这样的方法,它在使用Task.Factory.FromAsync()声明responseObject时挂起。

代码语言:javascript
复制
private async Task<string> post(string url, string postdata)
        {
            var request = WebRequest.Create(new Uri(url)) as HttpWebRequest;
            request.Method = "POST";

            // this works
            Task<Stream> requestStream = Task<Stream>.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, request);
            var sw = new StreamWriter(requestStream.Result);
            byte[] data = Encoding.UTF8.GetBytes(postdata);
            await requestStream.Result.WriteAsync(data, 0, data.Length);

            // this hangs
            Task<WebResponse> responseObject = Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, request); // Hangs here
            // Doesn't get to here
            var responseStream = responseObject.Result.GetResponseStream();
            var sr = new StreamReader(responseStream);
            string received = await sr.ReadToEndAsync();

            return received;
}

如果我手动运行Begin/End方法,它会运行得很好,如下所示:

代码语言:javascript
复制
        request.BeginGetRequestStream(async ar =>
        {
            var requestStream = request.EndGetRequestStream(ar);
            using (var sw = new StreamWriter(requestStream))
            {
                byte[] data = Encoding.UTF8.GetBytes(postdata);
                await requestStream.WriteAsync(data, 0, data.Length);
            }

            request.BeginGetResponse(async a =>
            {
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(a);
                var responseStream = response.GetResponseStream();
                using (var sr = new StreamReader(responseStream))
                {
                    string received = await sr.ReadToEndAsync();
                }

            }, null);
        }, null);

但是,在这种情况下,ReadToEndAsync()是在一个单独的线程上运行的,我希望该方法返回结果,这是不可能的,因为该方法在BeginGetResponse回调完成之前返回。

在这一点上,我认为我做这件事是大错特错的,而且是以完全错误的方式进行的,所以任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-12-31 15:45:39

首先:不要在异步方法中使用".Result“。这将阻塞正在运行您的方法的线程。改用"await“,这样当获得结果时,线程就会跳回你的方法。

代码的问题在于,您打开了一个请求流,但从未关闭过它。那么它应该在什么时候完成你的请求并发送它呢?它总是期待更多的输入到来,直到请求在超时时运行。您还没有设置content-type和content-length。

代码语言:javascript
复制
private async Task<string> post(string url, string postdata)
    {
        var request = WebRequest.Create(new Uri(url)) as HttpWebRequest;
        request.Method = "POST";

        byte[] data = Encoding.UTF8.GetBytes(postdata);
        request.ContentLength = data.Length;

        using (var requestStream = await Task<Stream>.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, request))
        {
            await requestStream.WriteAsync(data, 0, data.Length);
        }


        WebResponse responseObject = await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, request);
        var responseStream = responseObject.GetResponseStream();
        var sr = new StreamReader(responseStream);
        string received = await sr.ReadToEndAsync();

        return received;
}
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14098258

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档