所以我在我的应用程序中实现了一个方法,从一个站点下载给定漫画的图像,并将所述图像放入应用程序的AppData(localstate)文件夹中language
文件夹内title
}文件夹。
图像下载工作完美,除了我尝试一次下载多个图像集之外,结果在所涉及的文件夹中混合。
处理文件IO的方法:
private async Task<bool> SaveManga(Data.Posts.Content2 manga)
{
var folder = ApplicationData.Current.LocalFolder;
var safeName = Path.GetInvalidFileNameChars().Aggregate(manga.ContentInfo.ContentName, (current, c) => current.Replace(c, '_').Replace('.', '_'));
// Create folder for issue if does not exist
var issueFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(safeName, CreationCollisionOption.OpenIfExists);
// Create folder for language if does not exist
var langFolder = await issueFolder.CreateFolderAsync(manga.ContentInfo.ContentLanguage, CreationCollisionOption.OpenIfExists);
// Populate pages if page count is 0
if (manga.Pages == null)
manga.Pages = new Dictionary<int, Data.Posts.Page>();
if (manga.Pages.Count == 0)
{
if (NetworkInterface.GetIsNetworkAvailable() == false)
{
}
var pages = Fakku.GetMangaInfo(manga.ContentInfo.ContentUrl).Result.Pages;
for (var i = 0; i < pages.Count; i++)
{
var page = new Data.Posts.Page { Image = pages.Values.ElementAt(i).Image, Thumb = pages.Values.ElementAt(i).Thumb };
manga.Pages.Add(i, page);
}
}
var files = await langFolder.GetItemsAsync();
var fileCount = files.Count;
if (fileCount + 3 == manga.ContentInfo.ContentPages) return true;
var cbi = new BitmapImage(new Uri(manga.ContentInfo.ContentImages.Cover));
const string cname = "cover.jpg";
var wcbi = await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(cbi);
await wcbi.SaveToFile(langFolder, cname, CreationCollisionOption.OpenIfExists);
var sbi = new BitmapImage(new Uri(manga.ContentInfo.ContentImages.Sample));
const string sname = "sample.jpg";
var wsbi = await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(sbi);
await wsbi.SaveToFile(langFolder, sname, CreationCollisionOption.OpenIfExists);
for (var i = 1; i < manga.ContentInfo.ContentPages; i++)
{
var bi = new BitmapImage(new Uri(manga.Pages[i].Image));
//var x = await langFolder.CreateFileAsync(String.Format("{0}.png", i), CreationCollisionOption.ReplaceExisting);
var imgName = String.Format("{0}.jpg", i);
try
{
var wbi = await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(bi);
await wbi.SaveToFile(langFolder, imgName, CreationCollisionOption.OpenIfExists);
}
catch (Exception e)
{
var hResult = (uint)e.HResult;
if (hResult.Equals(0x80190194))
{
new MessageDialog("Error loading pages. \n If this is a sample manga, this behavior is to be expected.").ShowAsync();
break;
}
}
}
return true;
}
实施:
private async void SaveButton_Click(object sender, RoutedEventArgs e)
{
SaveButton.IsEnabled = false;
if (isSaved)
{
var i = defaultViewModel.ContentInfo;
Fakku.SavedManga.RemoveAll(x => x.ContentInfo.ContentUrl == i.ContentUrl);
isSaved = !isSaved;
SaveButton.Content = "Save";
var manga = defaultViewModel;
await RemoveManga(manga);
await ProcessSaved();
SaveButton.IsEnabled = true;
}
else if (!isSaved)
{
Fakku.SavedManga.Add(defaultViewModel);
isSaved = true;
SaveButton.Content = "Remove";
try
{
var manga = defaultViewModel;
//pendingWork = SaveManga(manga);
_saves.Enqueue(manga);
await AsyncParallelForEach(
_saves, async save => await SaveManga(manga), 8,
TaskScheduler.FromCurrentSynchronizationContext());
//HandleSaving();
await ProcessSaved();
}
catch (NullReferenceException)
{
}
SaveButton.IsEnabled = true;
}
}
AsParallel函数:
private static Task AsyncParallelForEach<T>(
IEnumerable<T> source, Func<T, Task> body,
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
TaskScheduler scheduler = null)
{
var options = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = maxDegreeOfParallelism
};
if (scheduler != null)
options.TaskScheduler = scheduler;
var block = new ActionBlock<T>(body, options);
foreach (var item in source)
block.Post(item);
block.Complete();
return block.Completion;
}
平行foreach的使用是我最近的尝试,取自this文章,但结果模仿我上面描述的内容,我觉得我仍然缺少一些非常重要的东西。
有人能指出我正确的方向吗?我正试图找到一种方法来处理这些下载,即同时处理SaveManga方法的多个实例,或者至少将它们排队等待完成。
编辑:我开始意识到我需要关注的是并行化,而不是异步性,如果我想同时运行下载,这是我更喜欢的。
答案 0 :(得分:0)
我认为问题在于您正在并行化初始化(文件夹创建+页数),然后它会混淆每一个。
我建议先进行初始化:
public async Task InitAsync(Data.Posts.Content2 manga){
var folder = ApplicationData.Current.LocalFolder;
var safeName = Path.GetInvalidFileNameChars().Aggregate(manga.ContentInfo.ContentName, (current, c) => current.Replace(c, '_').Replace('.', '_'));
// Create folder for issue if does not exist
var issueFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(safeName, CreationCollisionOption.OpenIfExists);
// Create folder for language if does not exist
var langFolder = await issueFolder.CreateFolderAsync(manga.ContentInfo.ContentLanguage, CreationCollisionOption.OpenIfExists);
// Populate pages if page count is 0
if (manga.Pages == null)
manga.Pages = new Dictionary<int, Data.Posts.Page>();
if (manga.Pages.Count == 0)
{
var pages = Fakku.GetMangaInfo(manga.ContentInfo.ContentUrl).Result.Pages;
for (var i = 0; i < pages.Count; i++)
{
var page = new Data.Posts.Page { Image = pages.Values.ElementAt(i).Image, Thumb = pages.Values.ElementAt(i).Thumb };
manga.Pages.Add(i, page);
}
}
var cbi = new BitmapImage(new Uri(manga.ContentInfo.ContentImages.Cover));
const string cname = "cover.jpg";
var wcbi = await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(cbi);
await wcbi.SaveToFile(langFolder, cname, CreationCollisionOption.OpenIfExists);
var sbi = new BitmapImage(new Uri(manga.ContentInfo.ContentImages.Sample));
const string sname = "sample.jpg";
var wsbi = await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(sbi);
await wsbi.SaveToFile(langFolder, sname, CreationCollisionOption.OpenIfExists);
}
然后只做这样的一些并行化,因为框架将足够智能来管理线程:):
List<Task> tasksToWait = new List<Task>();
for (var i = 1; i < manga.ContentInfo.ContentPages; i++)
{
taskToWait.Add(Task.Run(()=>SaveMangaPage(i));
}
await Task.WhenAll(tasksToWait );
await ProcessSaved();
使用SaveMangaPage:
public async Task SaveMangaPage(int pageNumber) {
var bi = new BitmapImage(new Uri(manga.Pages[pageNumber].Image));
//var x = await langFolder.CreateFileAsync(String.Format("{0}.png", pageNumber), CreationCollisionOption.ReplaceExisting);
var imgName = String.Format("{0}.jpg", pageNumber);
try
{
var wbi = await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(bi);
await wbi.SaveToFile(langFolder, imgName, CreationCollisionOption.OpenIfExists);
}
catch (Exception e)
{
var hResult = (uint)e.HResult;
if (hResult.Equals(0x80190194))
{
new MessageDialog("Error loading pages. \n If this is a sample manga, this behavior is to be expected.").ShowAsync();
break;
}
}
}
}