我有需要下载的图片列表。我正在使用BackgroundDownloader和DownloadOperation。我已放置进度条以显示下载的文件数。 UI总是比下载的文件更新1。任何人都可以指出我失踪的地方。
以下是代码:
C#
public sealed partial class MainPage : Page
{
int count = 0;
public StorageFile ErrorFile { get; set; }
private List<DownloadOperation> activeDownloads = new List<DownloadOperation>();
List<string> guid = new List<string>();
public MainPage()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await StartDownload();
}
private async Task StartDownload()
{
BackgroundDownloader downloader = new BackgroundDownloader();
downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
List<Task> downloadCompletionTasks = new List<Task>();
List<string> files = GetFiles();
totalCount.Text = (files.Count).ToString();
progressBar1.Maximum = (files.Count);
foreach (string url in files)
{
StorageFile file = null;
file = await ApplicationData.Current.LocalFolder.CreateFileAsync(DateTime.Now.Ticks.ToString() + ".jpg", CreationCollisionOption.ReplaceExisting);
DownloadOperation op = downloader.CreateDownload(new Uri(url), file);
activeDownloads.Add(op);
}
//This forloop cannot be clubbed with above for loop because progressChanged event is accessing activeDownloads.
//In case of clubbing with above loop collection modified loop will be thrown.
foreach (DownloadOperation op in activeDownloads)
{
Progress<DownloadOperation> progress = new Progress<DownloadOperation>(progressChanged);
CancellationTokenSource cancellationToken = new CancellationTokenSource();
downloadCompletionTasks.Add(op.StartAsync().AsTask(cancellationToken.Token, progress));
}
Task status = Task.WhenAll(downloadCompletionTasks);
}
private async void progressChanged(DownloadOperation downloadOperation)
{
foreach (DownloadOperation op in activeDownloads)
{
if (!guid.Contains(op.Guid.ToString()))
{
if (op.Progress.Status == BackgroundTransferStatus.Completed)
{
await UpdateUI(downloadOperation, op);
}
else if (op.Progress.Status == BackgroundTransferStatus.Error)
{
await UpdateUI(downloadOperation, op);
}
}
}
}
private async Task UpdateUI(DownloadOperation downloadOperation, DownloadOperation op)
{
guid.Add(op.Guid.ToString());
await this.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
count = count + 1; //guid count can be used as well
progressBar1.Value = count;
progressCount.Text = count.ToString();
});
}
private List<String> GetFiles()
{
List<string> imgurl = new List<string>();
imgurl.Add("http://images5.fanpop.com/image/photos/26700000/Snoopy-peanuts-26798453-1024-768.jpg");
imgurl.Add("http://images.fanpop.com/images/image_uploads/Peanut-Wallpapers-peanuts-99522_1024_768.jpg");
imgurl.Add("http://images5.fanpop.com/image/photos/25300000/peanuts-peanuts-25369428-800-600.jpg");
imgurl.Add("http://images6.fanpop.com/image/photos/37200000/Peanuts-Movie-Wallpaper-peanuts-37225534-3996-2160.jpg");
imgurl.Add("http://images.fanpop.com/images/image_uploads/Peanut-Wallpapers-peanuts-99520_1024_768.jpg");
imgurl.Add("http://4.bp.blogspot.com/-wU0ljNbhyUc/TYo-LLNzqiI/AAAAAAAACQU/YxAHEOAFfCk/s1600/snoopy+peanuts+desktop+wallpaper.jpg");
imgurl.Add("http://images5.fanpop.com/image/photos/26700000/Peanuts-peanuts-26798652-1024-768.jpg");
imgurl.Add("http://brandthunder.com/wp/wp-content/uploads/2014/07/Peanuts-Wallpaper.jpg");
imgurl.Add("http://3.bp.blogspot.com/-OT_HLjvXiSM/UXbByYXDU3I/AAAAAAAAAdo/6kQv7OO0v4I/s1600/snoopy-woodstock_00392750.jpg");
imgurl.Add("http://images6.fanpop.com/image/photos/33100000/Snoopy-wallpaper-snoopy-33124725-1024-768.jpg");
return imgurl;
}
}
的Xaml
<Grid Background="DarkBlue">
<!--<Grid Background="Black" Opacity="0.6" Grid.Row="0"/>-->
<Grid Grid.Row="0" VerticalAlignment="Center">
<Grid VerticalAlignment="Center" Grid.Row="0" Margin="50" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Downloading" x:Name="fileName" FontSize="20" Grid.Row="0"/>
<ProgressBar x:Name="progressBar1" IsIndeterminate="False" Grid.Row="1"/>
<!--<TextBlock x:Name="percentTextBlock" Text="{Binding TotalProgressPercent}" Grid.Row="2" HorizontalAlignment="Center"/>-->
<TextBlock FontSize="20" x:Name="progressCount" Text="0" Grid.Row="2" HorizontalAlignment="left"/>
<TextBlock FontSize="20" x:Name="totalCount" Text="50" Grid.Row="2" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Grid>
答案 0 :(得分:0)
这很可能是一个线程问题。将你的guid集合变成HashSet。如果事件同时被触发并且guid将被多次添加,那么检查guid是否是列表的一部分是可能的。 HashSet将阻止guid被添加两次。
您的计数变量不安全,因为同时调用该方法可能会覆盖它。您应该使用新的HashSet计数。
- 编辑 -
由于您已经有一个活动下载列表,只需删除像这样完成的那个:
private async void progressChanged(DownloadOperation downloadOperation)
{
var status = downloadOperation.Progress.Status;
if (status == BackgroundTransferStatus.Completed || status == BackgroundTransferStatus.Error)
{
await UpdateUI(downloadOperation);
}
}
private async Task UpdateUI(DownloadOperation downloadOperation)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
activeDownloads.Remove(downloadOperation);
var activeCount = activeDownloads.Count;
progressBar1.Value = activeCount;
progressCount.Text = activeCount.ToString();
});
}