optimize parallel task, and clear share bookmarkId

This commit is contained in:
2020-05-21 21:44:10 +08:00
parent f8d85ef729
commit 9ca58cc814
9 changed files with 237 additions and 70 deletions

View File

@ -170,6 +170,10 @@ namespace Pixiview
try try
{ {
favObj = Stores.LoadFavoritesIllusts(url); favObj = Stores.LoadFavoritesIllusts(url);
foreach (var o in favObj.Illusts)
{
o.BookmarkId = null;
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -175,7 +175,7 @@ namespace Pixiview
UserProfileImage = img == null UserProfileImage = img == null
? StyleDefinition.ProfileNone ? StyleDefinition.ProfileNone
: Stores.LoadUserProfileImage(img); : Stores.LoadUserProfileImage(img, true);
} }
} }

View File

@ -33,6 +33,7 @@ namespace Pixiview.Illust
private int startIndex; private int startIndex;
private int nextIndex; private int nextIndex;
private bool flag = false; private bool flag = false;
private ParallelTask task;
public FavoritesPage() public FavoritesPage()
{ {
@ -67,6 +68,16 @@ namespace Pixiview.Illust
} }
} }
public override void OnUnload()
{
if (task != null)
{
task.Dispose();
task = null;
}
base.OnUnload();
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustItem[] data) protected override IEnumerable<IllustItem> DoGetIllustList(IllustItem[] data)
{ {
return data; return data;
@ -300,14 +311,13 @@ namespace Pixiview.Illust
if (list.Length > 0) if (list.Length > 0)
{ {
#if LOG
for (var i = 0; i < list.Length; i++) for (var i = 0; i < list.Length; i++)
{ {
var item = list[i]; var item = list[i];
#if LOG
App.DebugPrint($"add bookmark ({item.BookmarkId}) - {item.Id}: {item.Title}"); App.DebugPrint($"add bookmark ({item.BookmarkId}) - {item.Id}: {item.Title}");
#endif
item.Image = StyleDefinition.DownloadBackground;
} }
#endif
nows.InsertRange(0, list); nows.InsertRange(0, list);
} }
} }
@ -316,21 +326,98 @@ namespace Pixiview.Illust
return; return;
} }
ParallelTask.Start("favorite.loadimages", 0, list.Length, Configs.MaxPageThreads, i => SyncRemoteFavorites(list);
}
private void SyncRemoteFavorites(IllustItem[] list)
{
for (var i = 0; i < list.Length; i++)
{ {
var illustItem = list[i]; var item = list[i];
var data = Stores.LoadIllustPreloadData(illustItem.Id); var data = Stores.LoadIllustPreloadData(item.Id, false);
if (data != null && data.illust.TryGetValue(illustItem.Id, out var illust)) if (data != null && data.illust.TryGetValue(item.Id, out var illust))
{ {
illust.CopyToItem(illustItem); illust.CopyToItem(item);
if (data.user.TryGetValue(illust.userId, out var user)) if (data.user.TryGetValue(illust.userId, out var user))
{ {
illustItem.ProfileUrl = user.image; item.ProfileUrl = user.image;
}
var url = item.ImageUrl;
if (url != null)
{
var image = Stores.LoadPreviewImage(url, false);
if (image == null)
{
image = Stores.LoadThumbnailImage(url, false);
}
if (image != null)
{
item.Image = image;
}
}
url = item.ProfileUrl;
if (url == null)
{
item.ProfileImage = StyleDefinition.ProfileNone;
}
else
{
var image = Stores.LoadUserProfileImage(url, false);
if (image != null)
{
item.ProfileImage = image;
}
} }
return true;
} }
App.DebugError("load.favorite", $"cannot fetch preload data, {illustItem.Id}, disposed."); }
return false;
list = list.Where(i => i.Image == null || i.ProfileImage == null).ToArray();
if (task != null)
{
task.Dispose();
task = null;
}
task = ParallelTask.Start("favorite.loadimages", 0, list.Length, Configs.MaxPageThreads, i =>
{
var item = list[i];
if (item.ImageUrl == null)
{
var data = Stores.LoadIllustPreloadData(item.Id, true, force: true);
if (data != null && data.illust.TryGetValue(item.Id, out var illust))
{
illust.CopyToItem(item);
if (data.user.TryGetValue(illust.userId, out var user))
{
item.ProfileUrl = user.image;
}
}
else
{
App.DebugError("load.favorite", $"cannot fetch preload data, {item.Id}, disposed.");
return false;
}
}
if (item.Image == null && item.ImageUrl != null)
{
item.Image = StyleDefinition.DownloadBackground;
var image = Stores.LoadThumbnailImage(item.ImageUrl, true, force: true);
if (image != null)
{
item.Image = image;
}
}
if (item.ProfileImage == null && item.ProfileUrl != null)
{
item.ProfileImage = StyleDefinition.ProfileNone;
var userImage = Stores.LoadUserProfileImage(item.ProfileUrl, true, force: true);
if (userImage != null)
{
item.ProfileImage = userImage;
}
}
return true;
}, () => }, () =>
{ {
Stores.SaveFavoritesIllusts(); Stores.SaveFavoritesIllusts();

View File

@ -598,7 +598,32 @@ namespace Pixiview.Illust
{ {
if (item.Image == null) if (item.Image == null)
{ {
item.Image = StyleDefinition.DownloadBackground; var url = Configs.GetThumbnailUrl(item.ImageUrl);
var image = Stores.LoadPreviewImage(url, false);
if (image == null)
{
image = Stores.LoadThumbnailImage(url, false);
}
if (image != null)
{
item.Image = image;
}
item.ImageUrl = url;
}
if (item.ProfileImage == null)
{
if (item.ProfileUrl == null)
{
item.ProfileImage = StyleDefinition.ProfileNone;
}
else
{
var image = Stores.LoadUserProfileImage(item.ProfileUrl, false);
if (image != null)
{
item.ProfileImage = image;
}
}
} }
item.IsFavorite = item.IsFavorite =
item.BookmarkId != null || item.BookmarkId != null ||
@ -616,30 +641,30 @@ namespace Pixiview.Illust
task.Dispose(); task.Dispose();
task = null; task = null;
} }
task = ParallelTask.Start("collection.load", 0, collection.Count, Configs.MaxThreads, i => var list = collection.Where(i => i.Image == null || i.ProfileImage == null).ToArray();
task = ParallelTask.Start("collection.load", 0, list.Length, Configs.MaxThreads, i =>
{ {
if (!collection.Running) if (!collection.Running)
{ {
return false; return false;
} }
var illust = collection[i]; var illust = list[i];
if (illust.ImageUrl != null)
if (illust.Image == null && illust.ImageUrl != null)
{ {
var url = Configs.GetThumbnailUrl(illust.ImageUrl); illust.Image = StyleDefinition.DownloadBackground;
var image = Stores.LoadPreviewImage(url, false); var image = Stores.LoadThumbnailImage(illust.ImageUrl, true, force: true);
if (image == null)
{
image = Stores.LoadThumbnailImage(url);
}
if (image != null) if (image != null)
{ {
illust.Image = image; illust.Image = image;
} }
} }
if (illust.ProfileUrl != null) if (illust.ProfileImage == null && illust.ProfileUrl != null)
{ {
var userImage = Stores.LoadUserProfileImage(illust.ProfileUrl); illust.ProfileImage = StyleDefinition.ProfileNone;
var userImage = Stores.LoadUserProfileImage(illust.ProfileUrl, true, force: true);
if (userImage != null) if (userImage != null)
{ {
illust.ProfileImage = userImage; illust.ProfileImage = userImage;

View File

@ -62,8 +62,9 @@ namespace Pixiview.Illust
{ {
return null; return null;
} }
return data.body.page.follow.Select(i => var illusts = data.body.page.follow.Select(i =>
data.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString())?.ConvertToItem()); data.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString())?.ConvertToItem());
return illusts;
} }
protected override IllustData DoLoadIllustData(bool force) protected override IllustData DoLoadIllustData(bool force)
@ -78,7 +79,10 @@ namespace Pixiview.Illust
return; return;
} }
await ScrollToTopAsync(scrollView); await ScrollToTopAsync(scrollView);
StartLoad(true);
lastUpdated = default;
StartLoad(false);
} }
private void SearchBar_SearchButtonPressed(object sender, EventArgs e) private void SearchBar_SearchButtonPressed(object sender, EventArgs e)

View File

@ -308,7 +308,7 @@ namespace Pixiview.Illust
{ {
if (user.ProfileUrl != null) if (user.ProfileUrl != null)
{ {
var userImage = Stores.LoadUserProfileImage(user.ProfileUrl); var userImage = Stores.LoadUserProfileImage(user.ProfileUrl, true);
if (userImage != null) if (userImage != null)
{ {
user.ProfileImage = userImage; user.ProfileImage = userImage;
@ -326,10 +326,10 @@ namespace Pixiview.Illust
if (illust.ImageUrl != null) if (illust.ImageUrl != null)
{ {
var url = Configs.GetThumbnailUrl(illust.ImageUrl); var url = Configs.GetThumbnailUrl(illust.ImageUrl);
var image = Stores.LoadPreviewImage(url, false); var image = Stores.LoadPreviewImage(url, true, force: false);
if (image == null) if (image == null)
{ {
image = Stores.LoadThumbnailImage(url); image = Stores.LoadThumbnailImage(url, true);
} }
if (image != null) if (image != null)
{ {

View File

@ -439,7 +439,7 @@ namespace Pixiview.Illust
} }
} }
item.Loading = true; item.Loading = true;
var image = Stores.LoadPreviewImage(item.PreviewUrl, force: force); var image = Stores.LoadPreviewImage(item.PreviewUrl, true, force: force);
if (image != null) if (image != null)
{ {
item.Image = image; item.Image = image;
@ -649,7 +649,7 @@ namespace Pixiview.Illust
isPreloading = true; isPreloading = true;
var illustItem = IllustItem; var illustItem = IllustItem;
// force to reload // force to reload
var preload = Stores.LoadIllustPreloadData(illustItem.Id, force); var preload = Stores.LoadIllustPreloadData(illustItem.Id, true, force: force);
if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust)) if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust))
{ {
illust.CopyToItem(illustItem); illust.CopyToItem(illustItem);

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xamarin.Forms; using Xamarin.Forms;
@ -108,9 +107,7 @@ namespace Pixiview.Utils
return null; return null;
} }
var task = new ParallelTask(tag, from, toExclusive, maxCount, action, complete); var task = new ParallelTask(tag, from, toExclusive, maxCount, action, complete);
Task.Run(task.Start); return task.Start();
//ThreadPool.QueueUserWorkItem(task.Start);
return task;
} }
private readonly object sync = new object(); private readonly object sync = new object();
@ -142,9 +139,19 @@ namespace Pixiview.Utils
this.complete = complete; this.complete = complete;
} }
private void Start() public ParallelTask Start()
{ {
var list = new List<Task>(); _ = ThreadPool.QueueUserWorkItem(DoStart);
return this;
}
private void DoStart(object state)
{
#if LOG
var sw = new System.Diagnostics.Stopwatch();
long lastElapsed = 0;
sw.Start();
#endif
for (int i = from; i < to; i++) for (int i = from; i < to; i++)
{ {
var index = i; var index = i;
@ -154,20 +161,30 @@ namespace Pixiview.Utils
{ {
break; break;
} }
#if LOG
var elapsed = sw.ElapsedMilliseconds;
if (elapsed - lastElapsed > 60000)
{
lastElapsed = elapsed;
App.DebugPrint($"WARNING: parallel task ({tag}), {count} tasks in queue, cost too much time ({elapsed:n0}ms)");
}
#endif
if (disposed) if (disposed)
{ {
#if LOG #if LOG
App.DebugPrint($"parallel task determinate, disposed ({tag})"); sw.Stop();
App.DebugPrint($"parallel task determinate, disposed ({tag}), cost time ({elapsed:n0}ms)");
#endif #endif
return; return;
} }
Thread.Sleep(100); Thread.Sleep(16);
} }
lock (sync) lock (sync)
{ {
count++; count++;
} }
list.Add(Task.Run(() => ThreadPool.QueueUserWorkItem(o =>
//Task.Run(() =>
{ {
try try
{ {
@ -178,7 +195,7 @@ namespace Pixiview.Utils
} }
catch (Exception ex) catch (Exception ex)
{ {
App.DebugError("parallel.start ({tag})", $"failed to run action, index: {i}, error: {ex.Message}"); App.DebugError($"parallel.start ({tag})", $"failed to run action, index: {index}, error: {ex}");
} }
finally finally
{ {
@ -187,21 +204,31 @@ namespace Pixiview.Utils
count--; count--;
} }
} }
})); });
} }
while (count > 0) while (count > 0)
{ {
#if LOG
var elapsed = sw.ElapsedMilliseconds;
if (elapsed - lastElapsed > 60000)
{
lastElapsed = elapsed;
App.DebugPrint($"WARNING: parallel task ({tag}), {count} tasks are waiting for end, cost too much time ({elapsed:n0}ms)");
}
#endif
if (disposed) if (disposed)
{ {
#if LOG #if LOG
App.DebugPrint($"parallel task determinate, disposed ({tag})"); sw.Stop();
App.DebugPrint($"parallel task determinate, disposed ({tag}), cost time ({elapsed:n0}ms)");
#endif #endif
return; return;
} }
Thread.Sleep(100); Thread.Sleep(16);
} }
#if LOG #if LOG
App.DebugPrint($"parallel task done ({tag})"); sw.Stop();
App.DebugPrint($"parallel task done ({tag}), cost time ({sw.ElapsedMilliseconds:n0}ms)");
#endif #endif
complete?.Invoke(); complete?.Invoke();
} }

View File

@ -379,29 +379,49 @@ namespace Pixiview.Utils
return true; return true;
} }
public static IllustPreloadBody LoadIllustPreloadData(string id, bool force = false) public static IllustPreloadBody LoadIllustPreloadData(string id, bool downloading, bool force = false)
{ {
var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json"); var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json");
var result = HttpUtility.LoadObject<IllustPreloadBody>( IllustPreloadBody result;
file, if (!force)
string.Format(Configs.UrlIllust, id), {
null, result = ReadObject<IllustPreloadBody>(file);
out _, if (result != null)
force: force,
action: content =>
{ {
var index = content.IndexOf(Configs.SuffixPreload); return result;
if (index > 0) }
else if (!downloading)
{
return null;
}
}
if (downloading)
{
result = HttpUtility.LoadObject<IllustPreloadBody>(
file,
string.Format(Configs.UrlIllust, id),
null,
out _,
force: force,
action: content =>
{ {
index += Configs.SuffixPreloadLength; var index = content.IndexOf(Configs.SuffixPreload);
var end = content.IndexOf('\'', index); if (index > 0)
if (end > index)
{ {
content = content.Substring(index, end - index); index += Configs.SuffixPreloadLength;
var end = content.IndexOf('\'', index);
if (end > index)
{
content = content.Substring(index, end - index);
}
} }
} return content;
return content; });
}); }
else
{
result = null;
}
if (result == null) if (result == null)
{ {
App.DebugPrint($"error when load preload data: force({force})"); App.DebugPrint($"error when load preload data: force({force})");
@ -567,22 +587,22 @@ namespace Pixiview.Utils
public static ImageSource LoadIllustImage(string url) public static ImageSource LoadIllustImage(string url)
{ {
return LoadImage(url, PersonalFolder, imageFolder); return LoadImage(url, PersonalFolder, imageFolder, true);
} }
public static ImageSource LoadPreviewImage(string url, bool downloading = true, bool force = false) public static ImageSource LoadPreviewImage(string url, bool downloading, bool force = false)
{ {
return LoadImage(url, PersonalFolder, previewFolder, downloading, force); return LoadImage(url, PersonalFolder, previewFolder, downloading, force);
} }
public static ImageSource LoadThumbnailImage(string url) public static ImageSource LoadThumbnailImage(string url, bool downloading, bool force = false)
{ {
return LoadImage(url, CacheFolder, thumbFolder); return LoadImage(url, CacheFolder, thumbFolder, downloading, force);
} }
public static ImageSource LoadUserProfileImage(string url) public static ImageSource LoadUserProfileImage(string url, bool downloading, bool force = false)
{ {
return LoadImage(url, CacheFolder, userFolder); return LoadImage(url, CacheFolder, userFolder, downloading, force);
} }
public static bool CheckIllustImage(string url) public static bool CheckIllustImage(string url)
@ -606,7 +626,7 @@ namespace Pixiview.Utils
return null; return null;
} }
private static ImageSource LoadImage(string url, string working, string folder, bool downloading = true, bool force = false) private static ImageSource LoadImage(string url, string working, string folder, bool downloading, bool force = false)
{ {
var file = Path.Combine(working, folder, Path.GetFileName(url)); var file = Path.Combine(working, folder, Path.GetFileName(url));
ImageSource image; ImageSource image;