- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在尝试实现启动画面。我已采取this tutorial作为起点。
我的 App.xaml.cs 中的 OnStartup 如下所示:
protected override void OnStartup(StartupEventArgs e)
{
//initialize the splash screen and set it as the application main window
splashScreen = new MySplashScreen();
this.MainWindow = splashScreen;
splashScreen.Show();
//in order to ensure the UI stays responsive, we need to
//do the work on a different thread
Task.Factory.StartNew(() =>
{
//we need to do the work in batches so that we can report progress
for (int i = 1; i <= 100; i++)
{
//simulate a part of work being done
System.Threading.Thread.Sleep(30);
//because we're not on the UI thread, we need to use the Dispatcher
//associated with the splash screen to update the progress bar
splashScreen.Dispatcher.Invoke(() => splashScreen.Progress = i);
splashScreen.Dispatcher.Invoke(() => splashScreen.MyText = i.ToString());
}
//once we're done we need to use the Dispatcher
//to create and show the main window
this.Dispatcher.Invoke(() =>
{
//initialize the main window, set it as the application main window
//and close the splash screen
var mainWindow = new MainWindow();
this.MainWindow = mainWindow;
mainWindow.Show();
splashScreen.Close();
});
});
}
public MainWindow()
{
InitializeComponent();
((App)Application.Current).splashScreen.Dispatcher.Invoke(() => ((App)Application.Current).splashScreen.MyText = "From MainWindow");
// do some stuff that takes a few seconds...
}
最佳答案
Dispatcher
已经忙于创建 MainWindow
当您使用 Dispatcher.Invoke
调用构造函数时.然后在MainWindow
的构造函数中你调用了Dispatcher
再次。 Dispatcher.Invoke
有效地将委托(delegate)排入调度程序队列。一旦第一个委托(delegate)运行完成,下一个委托(delegate)(在这种情况下是来自 MainWindow
的构造函数内部的委托(delegate))被出列并执行(总是相对于给定的 DispatcherPriority
)。这就是为什么你必须等到构造函数完成,即第一个委托(delegate)已经完成。
我强烈推荐使用 Progress<T>
这是从 .NET 4.5 ( Async in 4.5: Enabling Progress and Cancellation in Async APIs ) 开始的推荐进度报告方式。它的构造函数捕获当前 SynchronizationContext
并对其执行报告回调。由于 Progress<T>
的实例在 UI 线程上创建回调将在正确的线程上自动执行,因此没有 Dispatcher
不再需要。这将解决您的问题。此外,当在异步上下文中使用时,进度报告也可以使用取消。
我也推荐使用async/ await
来控制流量。目标是创建 MainWindow
的实例在 UI 线程上。
还要始终避免使用 Thread.Sleep
因为它会阻塞线程。在这种情况下,UI 线程将因此变得无响应并卡住。使用异步(非阻塞)await Task.Delay
反而。根据经验,替换所有对 Thread
的引用与 Task
,即任务并行库是首选方式 (Task-based asynchronous programming)。
我相应地重构了您的代码:
应用程序.xaml.cs
private SplashScreen { get; set; }
protected override async void OnStartup(StartupEventArgs e)
{
// Initialize the splash screen.
// The first Window shown becomes automatically the Application.Current.MainWindow
this.SplashScreen = new MySplashScreen();
this.SplashScreen.Show();
// Create a Progress<T> instance which automatically
// captures the current SynchronizationContext (UI thread)
// which makes the Dispatcher obsolete for reporting the progress to the UI.
// Pass a report (UI update) callback to the Progress<T> constructor,
// which will execute automatically on the UI thread.
// Because of the generic parameter which is in this case of type ValueTuple (C# 7),
// 'System.ValueTuple' is required to be referenced (use NuGet Package Manager to install).
// Alternatively replace the tuple with an arg class.
var progressReporter = new Progress<(int Value, string Message)>(ReportProgress);
// Wait asynchronously for the background task to complete
await DoWorkAsync(progressReporter);
// Override the Application.Current.MainWindow instance.
this.MainWindow = new MainWindow();
// Asynchronously wait until MainWindow is initialized
// Pass the Progress<T> instance to the method,
// so that MainWindow can report progress too
await this.MainWindow.InitializeAsync(progressReporter);
this.SplashScreen.Close();
this.MainWindow.Show();
}
private async Task DoWorkAsync(IProgress<(int Value, string Message)> progressReporter)
{
// In order to ensure the UI stays responsive, we need to
// do the work on a different thread
await Task.Run(
async () =>
{
// We need to do the work in batches so that we can report progress
for (int i = 1; i <= 100; i++)
{
// Simulate a part of work being done
await Task.Delay(30);
progressReporter.Report((i, i.ToString()));
}
});
}
// The progress report callback which is automatically invoked on the UI thread.
// Requires 'System.ValueTuple' to be referenced (see NuGet)
private void ReportProgress((int Value, string Message) progress)
{
this.SplashScreen.Progress = progress.Value;
this.SplashScreen.MyText = progress.Message;
}
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
public async Task InitializeAsync(IProgress<(int Value, string Message)> progressReporter)
{
await Task.Run(
() =>
{
progressReporter.Report((100, "From MainWindow"));
// Run the initialization routine that takes a few seconds
}
}
}
关于c# - 从不同窗口的构造函数更新 UI 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59448414/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!