Silverlight HttpWebRequest同步调用

4

在我的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个回答

2

Silverlight 不支持同步的 Web 请求。因此,我编写了 简单异步操作运行器。其中一个目标是能够像同步代码一样编写代码,然后修改它以与运行器代码一起使用。

首先,从第一部分中获取 AsyncOperationService 的小段代码,并将其添加到您的项目中(如果您觉得这篇文章有些沉重,不用担心,这对于实际使用不重要)。

使用您提供的代码作为“同步模板”,我们可以看到我们需要一些 AsyncOperation 的实现来处理 GetRequestStreamGetResponseStream,因此我们将编写它们并将它们添加到项目中:

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

如果你正在分块上传文件,那么你可能希望将进度报告到用户界面中。我建议你在手头上准备好这个AsyncOperation(注入到现有的AsyncOperationService类中):

    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

在执行同步函数时,绝对不能阻塞主 UI 线程。

您仍然可以使用异步机制以分块的方式上传大文件。如果您正在使用 WCF 服务,请查看this post。我曾经使用运行在 JAXWS 上的 Soap webservice 做过同样的事情,因此与您选择的后端无关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接