TaskFactory.FromAsync与BeginGetRequestStream / EndGetRequestStream挂起 [英] TaskFactory.FromAsync with BeginGetRequestStream/EndGetRequestStream hangs

查看:152
本文介绍了TaskFactory.FromAsync与BeginGetRequestStream / EndGetRequestStream挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的方法,宣称 responseObject 使用Task.Factory.FromAsync()

I have a method like this, that hangs when declaring responseObject using Task.Factory.FromAsync()

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;
}

它工作正常,如果我手动运行的开始/结束的方法,如:

It works fine if I manually run the Begin/End methods, like this:

        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回调之前该方法返回完成这是不可能的。

However, in that case, ReadToEndAsync() is run on a separate thread, and I want the method to return the result, which isn't possible since the method returns before the BeginGetResponse callback is finished.

在这一点上我觉得我做的这个可怕的错误,并会对此完全错误的方式,所以任何帮助将非常AP preciated。

At this point I think I am doing this horribly wrong and going about this completely the wrong way, so any help would be much appreciated.

推荐答案

首先:不要在异步方法使用。结果。这将阻止运行的方法的线程。用等待代替,因此线程跳回当结果被获取您的方法

First of all: Don't use ".Result" in async methods. This will block the thread that is running your method. Use "await" instead, so the thread jumps back to your method when the result is acquired.

与code的问题是,你打开一个请求流,但你永远不会关闭它。因此,当它应该会完成您的请求,并发送?它会永远希望有更多的投入来,直到请求超时运行。你也没有设置的内容类型和内容长度。

The problem with your code is that you open a request stream, but you never close it. So when should it expect to finish your request and send it? It'll always expect more input to come, until the request runs in a timeout. Also you have not set a content-type and content-length.

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;
}

这篇关于TaskFactory.FromAsync与BeginGetRequestStream / EndGetRequestStream挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆