gpt4 book ai didi

c# - 在暂停应用程序时访问 UI 线程?

转载 作者:太空狗 更新时间:2023-10-29 21:43:03 24 4
gpt4 key购买 nike

我有一个 UWP 应用程序,允许用户创建和修改文本文档。我很难让保存机制与应用挂起/恢复生命周期一起工作。

这是我的:

  1. 所有磁盘访问都在单独的后台线程上完成,以保持 UI 响应
  2. 该后台线程还序列化所有磁盘访问,以确保在任何时候都只发生一次读取或写入操作
  3. 保存文档前后,UI 会更新以指示保存正在进行中。这是通过 Dispatcher.RunAsync()
  4. 在 UI 线程上安排的

应用暂停时:

  • 暂停时,我必须最后一次保存文档,以确保所有更改都在磁盘上(应用程序可能会在暂停时终止)
  • 所以我请求一个ExtendedExecutionSession
  • 我在我的队列中安排了一个最后的保存操作
  • 然后我等待队列处理所有挂起的磁盘访问操作
  • 最后,我将扩展执行 session 标记为已完成

我的问题:

  • 已计划的保存操作完成其磁盘访问,然后尝试通过 Dispatcher.RunAsync() 更新主线程上的 UI。后台队列等待此任务完成,但它从未完成,因为到那时,UI 线程已经停止

→ 所以我最后的保存操作永远不会执行,因为后台队列卡在等待更新 UI。

这是一个流程图:

App suspension flow chart

出现的几个问题:

  1. 当应用暂停时,UI 线程究竟何时停止?仅当它空闲或“介于两者之间”时? IE。如果我通过 Dispatcher.RunAsync() 安排一个 block ,这至少会完成或“卡住”吗?
  2. 有没有办法让我检查当前窗口的 UI 线程是否已经停止,以便我知道我不能再在我的后台文件访问线程中访问它?
  3. 暂停应用程序时哪些线程停止运行?何时停止运行?
  4. 在应用暂停时,我的后台文件访问线程是否也有被停止的风险?

问题总结:

当应用程序暂停时,我必须确保等待后台线程上可能挂起的磁盘访问完成,然后再最终再次保存文档,以防我的应用程序稍后终止。

最佳答案

这听起来太熟悉了!

我从你的问题中了解到,保存操作以更新 UI 结束,但由于它在后台线程中运行,除非你使用 Dispatcher 安排它,否则它无法触及 UI。只是为了形象化,您的代码看起来像这样吗:

public async Task SaveAsync()
{
// .. save to disk ..

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// update UI here
}

// Save Complete!
}

如果是这样,问题是 UI 更新是排队后台操作的一部分,如果 UI 更新或 Dispatcher 本身阻止了任何操作,则在您到达之前不会开始其他操作//Save Complete! 行,如果 Dispatcher 从不执行您的操作,则不会发生这种情况。

与其将保存操作与 UI 更新联系起来,不如尝试公开将触发 UI 更新的事件。例如:

public event EventHandler SaveStarted;
public event EventHandler SaveCompleted;

public async Task SaveAsync()
{
SaveStarted?.Invoke(this, EventArgs.Empty);

// .. save to disk ..

SaveCompleted?.Invoke(this, EventArgs.Empty);
}

您的 View 可以将处理程序附加到这些事件并显示/隐藏适当的视觉效果,而您的挂起处理程序可以安全地调用 SaveAsync() 方法而无需担心 UI。

当 View Unloaded 时,确保分离这些事件处理程序。引发这些事件时,您的保存操作不会阻塞队列。


更新 1

是的,您的事件处理程序必须使用 Dispatcher 在 UI 线程上运行:

public void OnSaveCompleted(object sender, EventArgs e)
{
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// update UI here...
}
}

因为处理程序被强制返回void,所以它不会阻塞后台线程。


更新 2

听起来你们有一些紧密的耦合。您需要重新设计您的应用程序,以便您的文本文档逻辑位于一个单独的项目中。我总是在 .Net Standard 项目中编写代码,该项目强制退出所有 UI。该项目将不允许任何 UI 代码,从而使您的逻辑保持干净和解耦。

如果您的所有代码都位于 UWP 项目中,那么很容易开始包括 View 逻辑、XAML 控件,在您的情况下,您的应用程序部分中的 Dispatcher 与演示文稿。

在您的情况下,您需要弄清楚如何使您的文本文档逻辑成为文档状态的所有者,而不是 UI。 hasChanges 只能由拥有 SaveAsync() 的相同逻辑修改。如果在 UI 操作期间出现中断/阻塞/失败/等等,并且它从未成功地进入文本文档,那么它是一个不完整的操作,不应该成为文档的一部分,也不应该是文档的责任来担心关于它何时暂停并保存到磁盘。

如果 UWP 在这些操作之一期间出于任何原因终止了您的应用程序,那么它就消失了。您的下一个任务是弄清楚如何在应用程序再次唤醒时恢复此操作。

关于c# - 在暂停应用程序时访问 UI 线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47770053/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com