我正在尝试开发一个必须具有GUI组件的简单应用程序。它将是任务栏托盘中的服务,但必须每隔几分钟查询一次数据库以检查更改,然后将结果发布到Web服务器。它将全天候运行。
这是我的第一个应用程序,因此从SO获得了一些帮助。当我第一次使用FluentScheduler时,我遇到了麻烦(C# FluentScheduler Job not Repeating),但是通过控制台应用程序将其作为一个简单的概念证明。
当我尝试使用我学到的知识并使用我的Windows窗体解决方案实现它时,我根本无法使用它,因为一旦它运行Application.Run(ThisForm);
命令,调度程序就什么也没做。最终在排除故障时,我偶然发现了这个问题:
https://github.com/fluentscheduler/FluentScheduler/issues/169
我看到你正在使用类似Windows Forms / WPF应用程序的库。从GUI应用程序启动线程/任务是***的痛苦,也许这就是咬你的东西。手指交叉成为别的东西,在STA线程,调度员,同步上下文和同类游戏中潜水并不好玩。
所以现在我想知道我应该做什么?我是否应该将计划任务作为控制台应用程序开发,为WPF应用程序留下API进行通信,或者我应该解决他描述的痛苦并使其在WPF中工作?
由于这是我的第一个C#项目,将两个组件分开似乎相当复杂,但我愿意了解这是否是正确的选择。我在项目的早期阶段只是对每个所需功能的概念进行了证明,因此可以轻松切换到WPF,UWP或其他任何最合适的功能。它将具有最小的GUI,只需几个表格来填写用户名/密码类型的东西和同步选项。
即使这个FluentScheduler有大约25万次下载,也许有一个更好的下载没有你可能推荐的相同限制。
答案 0 :(得分:0)
根据您关联的早期帖子,我发现您的代码存在一些问题:
您对JobManager.Initialize
的调用无法访问,因为它发生在Application.Run
之后,会阻塞直到应用程序关闭(例如,当最后一个窗口关闭时)。
FluentScheduler
将安排您的作业在任意工作线程上运行,但您的操作会访问或操作UI元素。在WPF和Windows窗体中,您只能触摸主线程中的UI元素。如果你的工作需要触摸UI,它必须首先将自己编组回UI线程。
原始帖子中的预定操作没有意义:
Action someMethod = new Action(() =>
{
Form1 ThisForm = new Form1();
ThisForm.Text ="HELLO";
});
具体来说,您正在创建一个永不显示的新窗口,而不是修改已存在的窗口。
这是一个简单的示例项目,您应该可以将其作为起点。它显示当前时间,每秒更新一次。我使用WPF,因为我多年没有使用过Windows Forms,而且这些天没有令人信服的理由使用它。
<强> SchedulerText.xaml:强>
<Window x:Class="WpfTest.SchedulerTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock x:Name="_textBlock"
FontSize="18pt"
TextAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Window>
<强> SchedulerTest.xaml.cs:强>
using System;
using FluentScheduler;
namespace WpfTest
{
public partial class SchedulerTest
{
public SchedulerTest()
{
InitializeComponent();
JobManager.AddJob(
this.DoScheduledWork,
schedule => schedule.ToRunNow().AndEvery(1).Seconds());
}
private void DoScheduledWork()
{
// Go query your database, or do whatever your main job is.
// You don't want to do this on the UI thread, because it
// will block the thread and prevent user interaction.
DoPrimaryWorkOffUIThread();
// If you need to communicate some sort of result to the user,
// do it on the UI thread.
Dispatcher.Invoke(new Action(ShowResultsOnUIThread));
}
private DateTime _currentResult;
private void DoPrimaryWorkOffUIThread()
{
_currentResult = DateTime.Now;
}
private void ShowResultsOnUIThread()
{
_textBlock.Text = $"{_currentResult:h:mm:ss}";
}
}
}
请注意,您不必在Windows的构造函数中初始化作业,但这是最容易实现的地方。