c# - 后台任务正在阻塞 wpf .net 核心应用程序中的主线程
问题描述
我的软件中有一个后台任务,应该无限期运行。
重复该任务(以及将来可能还有其他任务)的代码如下所示:
public class RunTicketTasks
{
public async Task RunBackgroundTasks()
{
AssignTickets assignTickets = new AssignTickets();
while (true)
{
await assignTickets.AssignTicketCreator();
await Task.Delay(5 * 60 * 1000);
}
}
}
同时MainWindow.xaml
,据我所知,我有 WPF UI,它是应用程序的入口点。
在public MainWindow
我开始任务的方式如下:
public MainWindow()
{
InitializeComponent();
JiraBackgroundTasks.RunTicketTasks ticketTasks = new JiraBackgroundTasks.RunTicketTasks();
ticketTasks.RunBackgroundTasks();
}
显然,这会在同一个线程上启动任务(我相信)。任务已启动并成功运行,但由于长时间运行操作,UI 被阻塞。同时,当我取消注释最后一行时ticketTasks.RunBackgroundTasks();
,UI 运行良好。
如何在后台启动任务以使我的用户界面仍然响应?
编辑:
我以这种方式开始任务的原因是异常处理。我可以按照建议在不同的线程上成功启动任务Task.Run(async () => await ticketTasks.RunBackgroundTasks());
但是如果出现问题,我将不会收到任何异常。
如果抛出异常,如何启动不阻塞 UI 的任务并仍接收异常详细信息?
网上说的方法如下:
await Task.Run(() => ticketTasks.RunBackgroundTasks());
但这行不通,因为The await operator can only be used within an async method.
解决方案
一种方法是将任务包装在异步事件回调中:
public partial class MainWindow : Window
{
// I mocked your missing types, replace with your own
class AssignTickets
{
public Task AssignTicketCreator() => Task.CompletedTask;
}
public class RunTicketTasks
{
public async Task RunBackgroundTasks()
{
AssignTickets assignTickets = new AssignTickets();
int x = 0;
while (true)
{
await assignTickets.AssignTicketCreator();
await Task.Delay(1000);
var isRunningOnDispatcher = Application.Current.Dispatcher ==
System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread);
Trace.WriteLine($"One second passed, running on dispatcher: {isRunningOnDispatcher}");
// exception will also get thrown on the main thread
if (x++ > 3) throw new Exception("Hello!");
}
}
}
public MainWindow()
{
InitializeComponent();
// event fires on UI thread!
this.Loaded += async (sender, args) =>
{
try
{
await new RunTicketTasks().RunBackgroundTasks();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
};
}
}
推荐阅读
- android-studio - 按 ID 而非 findViewById 寻址元素
- python - 多处理让每个工作人员的会话保持打开状态
- python - remove() 函数后如何从列表理解中获取更新的列表
- intellij-idea - RubyMine (IntelliJ) 在本地和 GitHub 上显示不同的缩进
- scala - Scala List 上的 foldLeft vs foldRight vs tailrec
- lightgbm - 将 init_score 参数传递给二进制目标的 lightgbm 时,我是将初始预测作为概率还是作为 logit 值传递?
- sql - postgresql:如果不退出则创建用户
- javascript - 为什么我的 api 中的数据不会在我的 Vue 模板中呈现?
- mysql - 有没有办法防止涉及多列的 SQL 数据库中的重复条目?
- python - Scipy fsolve solving an equation with specific demand