Silverlight HttpWebRequest同步调用

时间:2011-04-04 11:39:09

标签: silverlight synchronization httpwebrequest

在我的silverlight应用程序中,我进行文件上传。我将文件分成块然后上传每个块。问题是我想同步使用HttpWebRequest。我的问题是确保所有请求都可以并且捕获异常。 Silverlight有可能吗?我想要像下面这样的东西:

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)
    {...}
}

你能给我一个提示我怎么能得到这个?

谢谢, Radu D

2 个答案:

答案 0 :(得分:2)

Silverlight不支持同步Web请求。出于这个原因,我写了Simple Asynchronous Operation Runner。其中一个目标是能够将代码编写为同步代码,然后修改代码以使用转轮代码。

首先从第1部分获取AsyncOperationService的一小部分代码并将其添加到您的项目中(如果您发现文章有点重,实际使用它并不重要,请不要担心)。

使用您已经提供的代码作为“同步模板”,我们可以看到AsyncOperationGetRequestStream需要几个GetResponseStream实现,因此我们会将这些代码添加到该项目也是: -

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类): - < / p>

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

现在我们可以创建代码的异步版本: -

 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 :(得分:1)

通过执行同步功能来阻止主UI线程绝对不行。

您仍然可以使用异步机制以块的形式上传大文件。如果您使用的是WCF服务,请查看this post。我使用在JAXWS上运行的Soap webservice做了同样的事情,所以它与你选择的后端无关。