具有调度操作的“简单”WPF

时间:2018-01-08 18:26:48

标签: c# wpf

我正在尝试开发一个必须具有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万次下载,也许有一个更好的下载没有你可能推荐的相同限制。

1 个答案:

答案 0 :(得分:0)

根据您关联的早期帖子,我发现您的代码存在一些问题:

  1. 您对JobManager.Initialize的调用无法访问,因为它发生在Application.Run之后,会阻塞直到应用程序关闭(例如,当最后一个窗口关闭时)。

  2. FluentScheduler将安排您的作业在任意工作线程上运行,但您的操作会访问或操作UI元素。在WPF和Windows窗体中,您只能触摸主线程中的UI元素。如果你的工作需要触摸UI,它必须首先将自己编组回UI线程。

  3. 原始帖子中的预定操作没有意义:

     Action someMethod = new Action(() =>
                             {
                                 Form1 ThisForm = new Form1();
                                 ThisForm.Text ="HELLO";
                             });
    

    具体来说,您正在创建一个永不显示的新窗口,而不是修改已存在的窗口。

  4. 这是一个简单的示例项目,您应该可以将其作为起点。它显示当前时间,每秒更新一次。我使用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的构造函数中初始化作业,但这是最容易实现的地方。