如何从异步任务有效地更新 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 技巧可能会有所帮助。
使用从 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 技巧可能会有所帮助。