C# 在Windows Phone 8中异步下载和保存文件
如何异步下载文件并将其保存到C# 在Windows Phone 8中异步下载和保存文件,c#,windows-phone-8,async-await,C#,Windows Phone 8,Async Await,如何异步下载文件并将其保存到IsolatedStorage? 我首先使用了WebClient,但是我不能等到完成,所以我找到了一些有用的代码 然而,这也不是完整的格式。我发现这个函数: public static Task<Stream> DownloadFile(Uri url) { var tcs = new TaskCompletionSource<Stream>(); var wc = new WebClient(); wc.OpenRea
IsolatedStorage
?
我首先使用了WebClient
,但是我不能等到完成,所以我找到了一些有用的代码
然而,这也不是完整的格式。我发现这个函数:
public static Task<Stream> DownloadFile(Uri url)
{
var tcs = new TaskCompletionSource<Stream>();
var wc = new WebClient();
wc.OpenReadCompleted += (s, e) =>
{
if (e.Error != null) tcs.TrySetException(e.Error);
else if (e.Cancelled) tcs.TrySetCanceled();
else tcs.TrySetResult(e.Result);
};
wc.OpenReadAsync(url);
return tcs.Task;
}
公共静态任务下载文件(Uri url)
{
var tcs=new TaskCompletionSource();
var wc=新的WebClient();
wc.OpenReadCompleted+=(s,e)=>
{
如果(e.Error!=null)tcs.TrySetException(e.Error);
否则,如果(如取消)tcs.TrySetCanceled();
其他tcs.TrySetResult(e.Result);
};
OpenReadAsync(url);
返回tcs.Task;
}
但是如何将此文件保存到隔离存储
?有人帮我完成这个功能 试试这样的方法(未经测试):
[]这篇文章应该有用。如果您需要稍微扩展您的方法,我会尝试这样做(虽然它没有经过测试,但应该可以工作):
(注释后重建-取消)
//首先定义取消令牌源-我将其设置为全局,以便CancelButton可以访问它
CancellationTokenSource cts=新的CancellationTokenSource();
枚举问题{确定,已取消,其他};//我的任务结果
//取消按钮事件
私有作废取消按钮\单击(对象发送者,路由目标e)
{
如果(this.cts!=null)
this.cts.Cancel();
}
//主要方法-我已经在下面的文本中对其进行了描述
公共异步任务从Web下载文件(Uri uriToDownload,字符串文件名,CancellationToken)
{
尝试
{
使用(Stream mystr=wait DownloadFile(uriToDownload))
使用(IsolatedStorageFile ISF=IsolatedStorageFile.GetUserStoreForApplication())
{
如果(ISF.FileExists(fileName))返回问题;
使用(IsolatedStorageFileStream文件=ISF.CreateFile(文件名))
{
const int BUFFER_SIZE=1024;
字节[]buf=新字节[缓冲区大小];
int字节读取=0;
而((bytesread=await mystr.ReadAsync(buf,0,BUFFER_SIZE))>0)
{
cToken.ThrowIfCancellationRequested();
file.Write(buf,0,bytesread);
}
}
}
返回问题。好的;
}
捕获(异常exc)
{
如果(exc为操作取消异常)
退货问题。取消;
否则返回问题。其他;
}
}
//下载
private async void Downlaud_Click(对象发送方、路由目标方)
{
cts=新的CancellationTokenSource();
Problem fileDownloaded=等待下载FileFromWeb(新Uri)(@)http://filedress/myfile.txt,UriKind.Absolute),“myfile.txt”,cts.Token);
交换机(文件下载)
{
案例问题。好的:
MessageBox.Show(“下载的文件”);
打破
案例问题。已取消:
MessageBox.Show(“下载已取消”);
打破
案例问题。其他:
违约:
显示(“其他下载问题”);
打破
}
}
我添加了取消令牌-这意味着您的下载操作可以在单击按钮后取消。单击。另一方面,如果Wait DownloadFile(uriToDownload)被取消,它将自动抛出OperationCancelled-然后您将捕获该异常并返回适当的结果。我还没有运行该代码,但它可能显示了主要思想。在我看来,像这样使用本机实现的最佳方式(包装Begin/End asynchronous API):
var url=newuri(UriString,UriKind.Absolute);
var fileName=Path.GetFileName(url.LocalPath);
var w=WebRequest.CreateHttp(url);
var response=await Task.Factory.fromsync(w.BeginGetResponse,w.EndGetResponse,null);
等待响应.GetResponseStream().CopyToAsync(新文件流(ApplicationData.Current.LocalFolder.Path+@“\”+文件名,FileMode.CreateNew));
在这种情况下,我们如何处理取消webclient下载。我设置了if(e.Cancelled)tcs.trysetconceled();。但是我怎样才能在主屏幕上查看呢thread@JMat我已经编辑了我的答案,并尝试添加取消功能。可能会有一些错误(我没有运行它)-但希望您能理解主要思想。是的,它工作正常,我在下载文件时遇到了一个奇怪的问题,内存不足异常。如果您有一些建议,请发表在Windows Phone 8上。WebClient
支持基于任务的异步编程(请参阅TaskAsync后缀方法)。但是,您可以从NuGet软件包中获得的方法更适合异步编程。您的代码将变得更干净。Task
返回的异步方法也应为后缀Async(已经有异步后缀方法的WebClient
的例外)。如果此问题与您链接的问题重复,请将其标记为重复问题,而不是留下这样的答案。如果不是重复问题,请留下完整的答案,而不是仅链接的答案。
try
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile("fileNameHere");
BitmapImage bitmap = new BitmapImage();
var stream = await DownloadFile(new Uri("http://someuri.com", UriKind.Absolute));
bitmap.SetSource(stream);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
}
}
catch (Exception ex)
{
//Exception handle appropriately for your app
}
// first define Cancellation Token Source - I've made it global so that CancelButton has acces to it
CancellationTokenSource cts = new CancellationTokenSource();
enum Problem { Ok, Cancelled, Other }; // results of my Task
// cancelling button event
private void CancellButton_Click(object sender, RoutedEventArgs e)
{
if (this.cts != null)
this.cts.Cancel();
}
// the main method - I've described it a little below in the text
public async Task<Problem> DownloadFileFromWeb(Uri uriToDownload, string fileName, CancellationToken cToken)
{
try
{
using (Stream mystr = await DownloadFile(uriToDownload))
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
if (ISF.FileExists(fileName)) return Problem.Other;
using (IsolatedStorageFileStream file = ISF.CreateFile(fileName))
{
const int BUFFER_SIZE = 1024;
byte[] buf = new byte[BUFFER_SIZE];
int bytesread = 0;
while ((bytesread = await mystr.ReadAsync(buf, 0, BUFFER_SIZE)) > 0)
{
cToken.ThrowIfCancellationRequested();
file.Write(buf, 0, bytesread);
}
}
}
return Problem.Ok;
}
catch (Exception exc)
{
if (exc is OperationCanceledException)
return Problem.Cancelled;
else return Problem.Other;
}
}
// and download
private async void Downlaod_Click(object sender, RoutedEventArgs e)
{
cts = new CancellationTokenSource();
Problem fileDownloaded = await DownloadFileFromWeb(new Uri(@"http://filedress/myfile.txt", UriKind.Absolute), "myfile.txt", cts.Token);
switch(fileDownloaded)
{
case Problem.Ok:
MessageBox.Show("File downloaded");
break;
case Problem.Cancelled:
MessageBox.Show("Download cancelled");
break;
case Problem.Other:
default:
MessageBox.Show("Other problem with download");
break;
}
}
var url = new Uri(UriString, UriKind.Absolute);
var fileName = Path.GetFileName(url.LocalPath);
var w = WebRequest.CreateHttp(url);
var response = await Task.Factory.FromAsync<WebResponse>(w.BeginGetResponse, w.EndGetResponse, null);
await response.GetResponseStream().CopyToAsync(new FileStream(ApplicationData.Current.LocalFolder.Path + @"\" + fileName, FileMode.CreateNew));