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

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

问题描述

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

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

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

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.

在这一点上,我认为我做的这件事大错特错,而且完全以错误的方式进行,因此非常感谢您的帮助.

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.

推荐答案

首先:不要在异步方法中使用.Result".这将阻止正在运行您的方法的线程.请改用await",这样线程在获取结果时会跳回您的方法.

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.

您的代码的问题在于您打开了一个请求流,但从未关闭它.那么它应该什么时候完成您的请求并发送它呢?它总是期望有更多输入,直到请求超时运行.此外,您还没有设置内容类型和内容长度.

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天全站免登陆