2012-05-16 23 views
84

Khi tôi làm let! read = from.AsyncRead buf trong F #, nó chặn và không trở lại cho đến khi cổng TCP bị chết. Tại sao? Và làm thế nào để sửa nó?Không đồng bộ POST trên WP7 và F #

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ó đang được gọi là từ mã này:

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

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

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. Cuộc gọi lại ResponseReady không bao giờ được tiếp cận.

Trong khi đó, mã này làm việc 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ể có được Fiddler2 làm việc với WP7.

EDIT: Chào mừng bạn đến với một yak. Tôi đã chuyển sang đồng cỏ xanh hơn bản thân mình;)

+9

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

+0

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

+0

Tôi chưa quên câu hỏi này; chỉ cần làm rất nhiều việc ngay bây giờ, sẽ đăng sửa ngay. – Henrik

Trả lời

1

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

Các vấn đề liên quan