后台任务阻塞 wpf .net 核心应用程序中的主线程
background task is blocking main thread in wpf .net core application
我的软件中有一个后台任务,应该 运行 无限期。
重复任务(以及未来可能的其他任务)的代码如下所示:
public class RunTicketTasks
{
public async Task RunBackgroundTasks()
{
AssignTickets assignTickets = new AssignTickets();
while (true)
{
await assignTickets.AssignTicketCreator();
await Task.Delay(5 * 60 * 1000);
}
}
}
同时我有 WPF UI MainWindow.xaml
据我所知这是应用程序入口点。
在 public MainWindow
内,我按以下方式开始任务:
public MainWindow()
{
InitializeComponent();
JiraBackgroundTasks.RunTicketTasks ticketTasks = new JiraBackgroundTasks.RunTicketTasks();
ticketTasks.RunBackgroundTasks();
}
显然,这会在同一个线程上启动任务(我相信)。任务已启动且 运行ning 成功,但 UI 由于长时间 运行ning 操作而被阻止。同时,当我取消注释最后一行 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);
}
};
}
}
我的软件中有一个后台任务,应该 运行 无限期。
重复任务(以及未来可能的其他任务)的代码如下所示:
public class RunTicketTasks
{
public async Task RunBackgroundTasks()
{
AssignTickets assignTickets = new AssignTickets();
while (true)
{
await assignTickets.AssignTicketCreator();
await Task.Delay(5 * 60 * 1000);
}
}
}
同时我有 WPF UI MainWindow.xaml
据我所知这是应用程序入口点。
在 public MainWindow
内,我按以下方式开始任务:
public MainWindow()
{
InitializeComponent();
JiraBackgroundTasks.RunTicketTasks ticketTasks = new JiraBackgroundTasks.RunTicketTasks();
ticketTasks.RunBackgroundTasks();
}
显然,这会在同一个线程上启动任务(我相信)。任务已启动且 运行ning 成功,但 UI 由于长时间 运行ning 操作而被阻止。同时,当我取消注释最后一行 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);
}
};
}
}