如何从异步任务有效地更新 WPF MainWindow

How to efficently update WPF MainWindow from an async task

使用从 public static class 抛出的事件从 async task 更新 WPF MainWindow 是一种可接受的方法吗?

在MainWindow.cs,我订阅了UI.TaskCompleted事件 在 UI.cs,我订阅了 AsyncTaskActions.TaskCompleted 事件。

使用此模式,AsyncTaskActions.TaskCompleted 引发异步任务完成。 UI 捕获事件并引发 UI.TaskCompleted。这样,事件在 MainWindow 代码中被捕获,我可以在其中使用 Displacher.Invoke 刷新显示的页面。最终结果是当任务完成并且任务仍在运行时我得到页面刷新 asynchronously.

Application design summary:

MainWindow: main window which can have several different page classes in content area within the main window.

Common.cs public static class contains a number of common methods through the UI in the application.

AsyncTaskActions.cs - class with a number of async common methods (ie download file)

代码片段:

    public partial class MainWindow 
        public MainWindow()
        {    
           UI.TaskCompleted += UI_TaskCompleted; 
        }

        void UI_TaskCompleted(EventArgs e)
        {
           Dispatcher.Invoke(new Action(this.PageRefresh));
        }

       public void PageRefresh()        
       {
           var page = ((ContentArea)).Content;
           if (page == null) return;

            switch (page.GetType().Name)
            {
                case "SearchPage":
                    ((SearchPage) page).SearchParts();
                    break;
                case "LegoPartPage":
                    ((LegoPartPage) page).LoadData();
                    break;
                case "LegoSetPage":
                    ((LegoSetPage) page).LoadData();
                    break;
                case "MainPage":
                    ((MainPage) page).LoadData();
                    break;
                case "MiniFigPage":
                    ((MiniFigPage) page).LoadData();
                    break;
            }
        }
   }

    public static class UI
    {
       public delegate void TaskComplete(EventArgs e);
       public static event TaskComplete TaskCompleted;

        public static async Task<int> DownloadPriceSummaryAsync(String itemNo, Int64 colorId)
        {
            var wAsyncTaskClasses = new AsyncTaskClasses();
            wAsyncTaskClasses.TaskCompleted += wAsyncTaskClasses_TaskCompleted;
            Task<HtmlDocument> task = wAsyncTaskClasses.DownloadPriceGuide(string.Format(Common.BrickLinkPrice, itemNo, colorId), itemNo, colorId);
            return await  wAsyncTaskClasses.ParsePriceSummaryAsync(task, itemNo, colorId);
        }
 }


public class AsyncTaskActions
{
    public delegate void TaskComplete(object sender, EventArgs e);
    public event TaskComplete TaskCompleted;

    public async Task<int> ParsePriceSummaryAsync(Task<HtmlDocument> task, string itemNo, Int64 colorId)
    {
        return await Task.Run(() => ParsePriceSummary(task, itemNo, colorId));
    }

    public int ParsePriceSummary(Task<HtmlDocument> task, string itemNo, Int64 colorId)
    {
         ... some code....

        if (null != TaskCompleted)
        {
            TaskCompleted(this, new EventArgs());
        }

        return recordCount;
    }

您正在使用 Dispatcher.BeginInvoke 将所有事件编组到 UI 上下文,这看起来很安全。

像往常一样,如果有效,就有效!


顺便说一句 - 这个设计没有太多我个人认为可以接受的地方。假设您来自程序或功能背景是否合理?将它放在 Code Review 以获取更多信息和一些 OO 技巧可能会有所帮助。