【问题标题】:Having trouble with background worker processes in WPF applicationWPF 应用程序中的后台工作进程出现问题
【发布时间】:2017-05-17 02:09:13
【问题描述】:

我发现了一些其他关于使用后台工作人员的文章,我在下面链接了这些文章。我使用了代码示例并尝试这样做以运行 3 个不同的 SQL 查询。在下面发布的代码中,当我闯入 RunBackGroundWorkerProcesses1 时,它确实停在那里并被调用,但是即使它在代码中,也永远不会调用 worker_DoWork1 的方法。我假设我误解了这一点,有人可以补充一下。

我用作参考的链接: WPF Multithreading

代码:

public CallInformationMainScreen()
        {
            InitializeComponent();    

//This is where i call the background processes
            RunBackGroundWorkerProcesses1();
            RunBackGroundWorkerProcesses2();
            RunBackGroundWorkerProcesses3();    
        }
        #endregion

        #region Methods used to generate data for the UI
        public string DisplayTotalDailyCalls()
        {
            DailyCallsQuery db = new DailyCallsQuery();
            return db.GetNumber(SkillNumber);
        }
        public string DisplayTotalLastSevenCalls()
        {
            PrevSevenCallQuery db = new PrevSevenCallQuery();
            return db.GetNumber(SkillNumber);
        }
        public string DisplayDailyAbandonCalls()
        {
            DailyAbandonQuery db = new DailyAbandonQuery();
            return db.GetNumber(SkillNumber);
        }    


        #endregion

        #region Background worker processes        
        private void RunBackGroundWorkerProcesses1()
        {
            BackgroundWorker worker = new BackgroundWorker();            
            worker.DoWork += new DoWorkEventHandler(worker_DoWork1);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

            System.Timers.Timer t = new System.Timers.Timer(10000); //  10 second intervals
            t.Elapsed += (sender, e) =>
            {
                // Don't try to start the work if it's still busy with the previous run...
                if (!worker.IsBusy)
                    worker.RunWorkerAsync();
            };
        }
        private void RunBackGroundWorkerProcesses2()
        {
            BackgroundWorker worker = new BackgroundWorker();           
            worker.DoWork += new DoWorkEventHandler(worker_DoWork2);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

            System.Timers.Timer t = new System.Timers.Timer(10000); //  10 second intervals
            t.Elapsed += (sender, e) =>
            {
                // Don't try to start the work if it's still busy with the previous run...
                if (!worker.IsBusy)
                    worker.RunWorkerAsync();
            };
        }
        private void RunBackGroundWorkerProcesses3()
        {
            BackgroundWorker worker = new BackgroundWorker();            
            worker.DoWork += new DoWorkEventHandler(worker_DoWork3);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

            System.Timers.Timer t = new System.Timers.Timer(10000); //  10 second intervals
            t.Elapsed += (sender, e) =>
            {
                // Don't try to start the work if it's still busy with the previous run...
                if (!worker.IsBusy)
                    worker.RunWorkerAsync();
            };
        }

        private void worker_DoWork1(object sender, DoWorkEventArgs e)
        {
            // Whatever comes back from the lengthy process, we can put into e.Result            
            TotalDailyCalls = DisplayTotalDailyCalls();
            e.Result = TotalDailyCalls;
        }
        private void worker_DoWork2(object sender, DoWorkEventArgs e)
        {
            // Whatever comes back from the lengthy process, we can put into e.Result            
            TotalDailyLast7Days = DisplayTotalLastSevenCalls();
            e.Result = TotalDailyCalls;
        }
        private void worker_DoWork3(object sender, DoWorkEventArgs e)
        {
            // Whatever comes back from the lengthy process, we can put into e.Result
            TotalDailyAbandon = DisplayDailyAbandonCalls();
            e.Result = TotalDailyAbandon;
        }

        private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            {
                // handle the System.Exception
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                // now handle the case where the operation was cancelled... 
                ErrorHolder = "The operation was cancelled";
            }
            else
            {
                // Finally, handle the case where the operation succeeded
                ErrorHolder = e.Result.ToString();
            }
        }
        #endregion

【问题讨论】:

  • 你想用这段代码做什么?仅仅是您试图在后台重复运行这三个查询中的每一个吗?
  • 是的,这些号码是进入呼叫队列的呼叫,每隔几分钟就会更新一次。由于下面的答案和我错过的简单计时器启动,我得到它后至少要调整它现在看起来正在执行的功能。
  • 有一种非常简单的方法可以做到这一点。我会弹出一个答案给你看。

标签: c# wpf


【解决方案1】:

你没有启动你的计时器。见Timer.Start Method ()

    private void RunBackGroundWorkerProcesses1()
    {
        BackgroundWorker worker = new BackgroundWorker();            
        worker.DoWork += new DoWorkEventHandler(worker_DoWork1);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

        System.Timers.Timer t = new System.Timers.Timer(10000); //  10 second intervals
        t.Elapsed += (sender, e) =>
        {
            // Don't try to start the work if it's still busy with the previous run...
            if (!worker.IsBusy)
                worker.RunWorkerAsync();
        };
        t.Start(); // Start the timer
    }

【讨论】:

    【解决方案2】:

    我发布此内容是为了演示一种更简单的方法。这并不意味着直接回答这个问题。

    如果您使用 NuGet "System.Reactive" 和相关的 WPF 库,您可以这样做:

    IDisposable subscription =
        new []
        {
            Observable.Interval(TimeSpan.FromSeconds(10.0)).Select(x => DisplayTotalDailyCalls()),
            Observable.Interval(TimeSpan.FromSeconds(10.0)).Select(x => DisplayTotalLastSevenCalls()),
            Observable.Interval(TimeSpan.FromSeconds(10.0)).Select(x => DisplayDailyAbandonCalls()),
        }
        .Merge()
        .ObserveOnDispatcher()
        .Subscribe(x => ErrorHolder = x, e => MessageBox.Show(e.Error.Message));
    

    就是这样。任务完成。从技术上讲,您的所有代码都在一行代码中。

    【讨论】:

    • 天哪。哈哈。只是为了正确理解这一点,它取代了我所有的三个后台工作方法?这仍然允许它们作为后台进程运行?这一切的原因是每次触发这些 SQL 方法之一时,它都会锁定应用程序。所以我需要确保查询是作为后台进程发生的。
    • 实际上这也将取代我完成的和我所有的工作方法。哇。
    • @mrcavanaugh09 - 是的,没错。一切都在后台。每次运行之间都有 10 秒的间隔,全部并行运行,并且全部替换代码中的所有方法。
    • @mrcavanaugh09 - 如果你想停止运行代码,只需调用subscription.Dispose();
    【解决方案3】:

    BackgroundWorker.RunWorkerAsync() 仅在Timer.Elapsed 事件被触发时被调用。由于计时器设置为 10 秒间隔,BackgroundWorker 不会在 10 秒内启动。您可能应该在创建和初始化它之后调用BackgroundWorker.RunWorkerAsync(),以便它立即启动。

    【讨论】:

    • backgroundworker.runworkerasync() 已在每个方法的 if 语句中调用。我还等了几分钟,应用程序正在运行,没有一个 SQL Query 方法被命中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    相关资源
    最近更新 更多