在我的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
答案 0 :(得分:2)
Silverlight不支持同步Web请求。出于这个原因,我写了Simple Asynchronous Operation Runner。其中一个目标是能够将代码编写为同步代码,然后修改代码以使用转轮代码。
首先从第1部分获取AsyncOperationService
的一小部分代码并将其添加到您的项目中(如果您发现文章有点重,实际使用它并不重要,请不要担心)。
使用您已经提供的代码作为“同步模板”,我们可以看到AsyncOperation
和GetRequestStream
需要几个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做了同样的事情,所以它与你选择的后端无关。