Zaman uyumsuz POST, WP7 ve F # üzerinde başarısız oluyor


87

let! read = from.AsyncRead bufF # ile yaptığım zaman , TCP soketi bitene kadar engelliyor ve geri dönmüyor. Neden? Ve nasıl düzeltirim?

Kodu:

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 ()

Bu koddan çağrılıyor:

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

ve Windows Phone 7.1 öykünücüsünden bu kodla HTTP üzerinden istenir:

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

Başarısızca. Geri ResponseReadyaramaya asla ulaşılmaz.

Bu arada, bu kod mükemmel çalışıyor:

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

Fiddler2'nin WP7 ile çalışmasını sağlayamadım.

DÜZENLEME: Bir yak'a hoş geldiniz. Daha yeşil otlaklara kendim taşındım;)


9
Eğer from.AsyncReadbloklar uzak sunucu herhangi bayt göndermez demekse o.
qehgt

Akışın düzgün kapanmaması sorunundan kurtuldum, ancak yine de alıcı tarafta 40 bayt büyüklüğünde dosyalar alıyorum ve WP'de mevcut olmamak yerine NotSupportedException'ı engelleyen birçok işlem var , bu yüzden hata ayıklamak gerçekten acı verici. Ona vardığımda tam bir çözüm sunacağım.
Henrik

Bu soruyu unutmadım; Şu anda yapılacak çok şey var, kısa süre sonra düzeltmeyi yayınlayacak.
Henrik


2
Bir TCP soketinden sonsuz miktarda bayt talep ettiğinizde bu beklenen davranış değil mi?
jyoung

Yanıtlar:


1

BufferStream INput çıktısını göndermeden ve kullanmadan önce baytları koymalısınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.