浏览代码

Mae Poster Dispatcher block main thread

Kenric Nugteren 4 天之前
父节点
当前提交
4dabbb351c
共有 1 个文件被更改,包括 76 次插入16 次删除
  1. 76 16
      prs.desktop/Utils/PostUtils.cs

+ 76 - 16
prs.desktop/Utils/PostUtils.cs

@@ -187,48 +187,106 @@ internal class PosterProgressDispatcher : IPosterDispatcher
 {
     private string Message;
 
+    private TaskCompletionSource _yield = new();
+    private TaskCompletionSource? _continue = new();
+
+    private Task? _queue;
+
+    private string? _setMessage;
+
     public PosterProgressDispatcher()
     {
         Message = "Loading Data";
-        Progress.Show(Message);
     }
 
     public Task ExecuteAsync(Action action)
     {
-        return App.Current.Dispatcher.BeginInvoke(() =>
+        var taskCompletionSource = new TaskCompletionSource();
+        _queue = new Task(() =>
         {
-            Progress.Close();
-            action();
-            Progress.Show(Message);
-        }).Task;
+            try
+            {
+                action();
+                taskCompletionSource.SetResult();
+            }
+            catch(Exception e)
+            {
+                taskCompletionSource.SetException(e);
+            }
+        });
+        _continue = new();
+        _yield.TrySetResult();
+        return Task.WhenAll(_continue.Task, taskCompletionSource.Task);
     }
 
     public Task<T> ExecuteAsync<T>(Func<T> func)
     {
         var taskCompletionSource = new TaskCompletionSource<T>();
-        App.Current.Dispatcher.BeginInvoke(() =>
+        _queue = new Task(() =>
         {
             try
             {
-                Progress.Close();
                 var result = func();
-                Progress.Show(Message);
                 taskCompletionSource.SetResult(result);
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 taskCompletionSource.SetException(e);
             }
         });
-        return taskCompletionSource.Task;
+        _continue = new();
+        _yield.TrySetResult();
+        return _continue.Task.ContinueWith(task => taskCompletionSource.Task.Result);
     }
 
     public void Report(string report)
     {
-        App.Current.Dispatcher.BeginInvoke(() =>
+        Message = report;
+        _setMessage = report;
+        _continue = new();
+        _yield.TrySetResult();
+        _continue.Task.Wait();
+    }
+
+    public void WaitTask(Task task)
+    {
+        _yield = new();
+        task.ContinueWith(t => _yield.TrySetResult());
+        while (true)
         {
-            Progress.SetMessage(report);
-        });
+            Progress.ShowModal(Message, progress =>
+            {
+                while (true)
+                {
+                    _yield.Task.Wait();
+                    if(_setMessage is not null)
+                    {
+                        progress.Report(_setMessage);
+                        _yield = new();
+                        _setMessage = null;
+                        _continue?.SetResult();
+                        _continue = null;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            });
+            if(_queue is not null)
+            {
+                _yield = new();
+                _queue.RunSynchronously();
+                _queue = null;
+                _continue?.SetResult();
+                _continue = null;
+            }
+            else
+            {
+                break;
+            }
+        }
+
     }
 }
 
@@ -246,7 +304,7 @@ public static class PostUtils
             try
             {
                 var dispatcher = new PosterProgressDispatcher();
-                var result = await Task.Run(() =>
+                var task = Task.Run(() =>
                 {
                     return PosterUtils.Process(model,
                         engine =>
@@ -255,9 +313,11 @@ public static class PostUtils
                         },
                         engine =>
                         {
-                            App.Current.Dispatcher.Invoke(() => Progress.Close());
                         });
                 });
+                dispatcher.WaitTask(task);
+                Progress.Close();
+                var result = await task;
                 if (result is null)
                 {
                     MessageWindow.ShowMessage($"Processing failed", "Processing failed");