Async POST không thành công trên WP7 và F #


87

Khi tôi thực hiện let! read = from.AsyncRead buftrong F #, nó sẽ chặn và không quay trở lại cho đến khi ổ cắm TCP chết. Tại sao? Và tôi phải sửa nó như thế nào?

Mã của nó:

module StreamUtil

open System.IO

/// copy from 'from' stream to 'toStream'
let (|>>) (from : Stream) (toStream : Stream) =
  let buf = Array.zeroCreate<byte> 1024
  let rec doBlock () =
    async {
      let! read = from.AsyncRead buf
      if read <= 0 then
        toStream.Flush()
        return ()
      else
        do! toStream.AsyncWrite(buf, 0, read)
        return! doBlock () }
  doBlock ()

Nó được gọi từ mã này:

use fs = new FileStream(targPath, FileMode.CreateNew, FileAccess.ReadWrite)
do! req.InputStream |>> fs

và được yêu cầu qua HTTP với mã này từ trình giả lập Windows Phone 7.1:

public void Send()
{
    var b = new UriBuilder(_imageService.BaseUrl) {Path = "/images"};

    var req = WebRequest.CreateHttp(b.Uri);
    req.ContentType = "image/jpeg";
    req.Method = "POST";
    var imgLen = SelectedImage.ImageStream.Length;
    req.Headers[HttpRequestHeader.ContentLength] = imgLen.ToString(CultureInfo.InvariantCulture);
    req.Accept = "application/json";
    req.BeginGetRequestStream(RequestReady, new ReqState(req, imgLen));
}

void RequestReady(IAsyncResult ar)
{
    var state = (ReqState)ar.AsyncState;
    var req = state.Request;

    var reqStream = req.EndGetRequestStream(ar);

    SmartDispatcher.BeginInvoke(() =>
        {
            using (var sw = new StreamWriter(reqStream))
            using (var br = new BinaryReader(SelectedVoucher.ImageStream))
            {
                var readBytes = br.ReadBytes(state.ImgLen);

                // tried both 2
                sw.Write(readBytes);
                //sw.Write(Convert.ToBase64String(readBytes));
                sw.Flush();
                sw.Close();
            }
            req.BeginGetResponse(ResponseReady, req);
        });
}

// WHY IS IT YOU ARE NOT CALLED???
void ResponseReady(IAsyncResult ar)
{
    try
    {
        var request = (HttpWebRequest)ar.AsyncState;
        var response = request.EndGetResponse(ar);

        SmartDispatcher.BeginInvoke(() =>
            {
                var rdr = new StreamReader(response.GetResponseStream());
                var msg = rdr.ReadToEnd();

                var imageLocation = response.Headers["Location"];

                Debug.WriteLine(msg);
                Debug.WriteLine(imageLocation);
            });
    }
    catch (WebException ex)
    {
        Debug.WriteLine(ex.ToString());
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.ToString());
    }
}

Không thành công. Không ResponseReadybao giờ gọi lại được.

Trong khi đó, mã này hoạt động tuyệt vời:

open System
open System.Net.Http // WebAPI nuget

let sync aw = Async.RunSynchronously aw

let postC<'a> (c : HttpClient) (r : Uri) (cont : HttpContent) =
  let response = sync <| Async.AwaitTask( c.PostAsync(r, cont) )
  let struc:'a = sync <| deserialize<'a> response
  response, struc

let withContent<'a> (fVerb : (HttpClient -> Uri -> HttpContent -> _ * 'a))=
  let c = new HttpClient()
  fVerb c

[<Test>]
let ``POST /images 201 + Location header`` () =
  let post = withContent<MyImage> postC
  let bytes = IO.File.ReadAllBytes("sample.jpg")
  let hash = SHA1.Create().ComputeHash(bytes) |> Convert.ToBase64String
  let pic = new ByteArrayContent(bytes)
  pic.Headers.Add("Content-Type", "image/jpeg")
  pic.Headers.Add("X-SHA1-Hash", hash)
  let resp, ri = (resource "/images", pic) ||> post

  resp.StatusCode =? Code.Created
  ri.sha1 =? hash
  mustHaveHeaders resp

Tôi không thể làm cho Fiddler2 hoạt động với WP7.

CHỈNH SỬA: Chào mừng bạn đến với yak. Tôi đã tự mình chuyển đến những đồng cỏ xanh tươi hơn;)


9
Nếu from.AsyncReadkhối điều đó có nghĩa là máy chủ từ xa không gửi bất kỳ byte nào.
qehgt

Tôi đã tránh khỏi vấn đề luồng không đóng đúng cách, nhưng tôi vẫn chỉ nhận được các tệp có kích thước lớn 40 byte ở phía nhận và trên WP có rất nhiều hoạt động đang chặn ném NotSupportedException thay vì không khả dụng , vì vậy rất khó gỡ lỗi. Tôi sẽ đăng một giải pháp hoàn chỉnh khi tôi đến nó.
Henrik

Tôi vẫn chưa quên câu hỏi này; chỉ có nhiều việc phải làm ngay bây giờ, sẽ sớm đăng bản sửa lỗi.
Henrik

5
Điều này có thể hữu ích cho bạn nếu bạn đang cố gắng làm cho fiddler hoạt động với thiết bị di động: registerofaninja.com/blog/2010/11/09/…
Alpha

2
Đây không phải là hành vi được mong đợi khi bạn yêu cầu số lượng byte vô hạn từ ổ cắm TCP?
jyoung

Câu trả lời:


1

YOu nên đặt các byte vào trước khi gửi và sử dụng đầu ra BufferStream INput

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.