2011-04-04 61 views
4

在我的silverlight應用程序中,我做文件上傳。我將文件分成塊,然後上傳每個塊。問題是我想同步使用HttpWebRequest。我的主題是確保所有請求都可以並確定例外情況。這在Silverlight中是可行的嗎?我想要sopmething像:Silverlight HttpWebRequest syncronous調用

while(chunk) 
{ 
    try{ 
    HttpWebRequest req = ... 
    req.BeginGetRequestStream(new AsyncCallback(WriteCallback), req); 
    //add data into request stream 
    req.BeginGetResponseStream(new AsyncCallback(ReadCallback), req); 
    //parse the response 
    chunk = new Chunk(); 
    }catch(Exception ex) 
    {...} 
} 

你能給我一個提示我怎麼能得到這個?

感謝, 拉杜d

回答

2

Silverlight不支持同步Web請求。爲此,我寫了Simple Asynchronous Operation Runner。其中一個目標是能夠編寫代碼,就好像它是同步的,然後修改它以使用runner代碼。

首先從第1部分獲得AsyncOperationService的小塊代碼,並將其添加到項目中(如果發現文章有點過重,那麼實際使用它並不重要)。

使用你已經爲「同步模板」所提供的代碼,我們可以看到,我們需要GetRequestStreamGetResponseStream幾個AsyncOperation實現,所以我們寫的那些它們添加到項目,以及: -

public static class WebRequestAsyncOps 
{ 
    public static AsyncOperation GetRequestStreamOp(this WebRequest request, Action<Stream> returnResult) 
    { 
     return (completed) => 
     { 
      request.BeginGetRequestStream((result) => 
      { 
       try 
       { 
        returnResult(request.EndGetRequestStream(result)); 
        completed(null); 
       } 
       catch (Exception err) 
       { 
        completed(err); 
       } 
      }, null); 
     }; 
    } 

    public static AsyncOperation GetResponseOp(this WebRequest request, Action<WebResponse> returnResult) 
    { 
     return (completed) => 
     { 
      request.BeginGetResponse((result) => 
      { 
       try 
       { 
        returnResult(request.EndGetResponse(result)); 
        completed(null); 
       } 
       catch (Exception err) 
       { 
        completed(err); 
       } 
      }, null); 
     }; 
    } 
} 

現在,如果你是分塊上傳一個文件,你可能會想報告進展到UI所以我建議你有這個AsyncOperation手頭以及(在注入到現有AsyncOperationService類): -

public static AsyncOperation SwitchToUIThread() 
    { 
     return (completed => Deployment.Current.Dispatcher.BeginInvoke(() => completed(null))); 
    } 

現在我們可以creare代碼的異步版本: -

IEnumerable<AsyncOperation> Chunker(Action<double> reportProgress) 
{ 
    double progress = 0.0; 
    Chunk chunk = new Chunk(); 
    // Setup first chunk; 
    while (chunk != null) 
    { 
      Stream outStream = null; 
      HttpWebRequest req = ... 

      yield return req.GetRequestStreamOp(s => outStream = s); 

      // Do stuff to and then close outStream 
      WebResponse response = null; 

      yield return req.GetResponseOp(r => response = r); 

      // Do stuff with response throw error is need be. 
      // Increment progress value as necessary. 

      yield return AsyncOperationService.SwitchToUIThread(); 

      reportProgress(progress); 

      chunk = null; 
      if (moreNeeded) 
      { 
      chunk = new Chunk(); 
      // Set up next chunk; 
      } 
     } 
} 

最後你只需要運行它,並處理任何錯誤: -

Chunker.Run((err) => 
{ 
    if (err == null) 
    { 
      // We're done 
    } 
    else 
    { 
      // Oops something bad happened. 
    } 

}); 
1

這是絕對不行的通過執行同步功能來阻塞主UI線程。

您仍然可以使用異步機制以塊的形式上傳大文件。如果您使用的是WCF服務,請檢查this post。我使用在JAXWS上運行的SOAP web服務完成了同樣的事情,因此它與您的後端選擇無關。