BacgroundWorkerCompleted не выполняется

#c# #multithreading #backgroundworker

#c# #многопоточность #backgroundworker

Вопрос:

Использование C # .NET 4.0

Я пытаюсь использовать BackgroundWorker для получения списка служб на удаленном компьютере. Это выполняется в фоновом режиме, поэтому пользовательский интерфейс остается отзывчивым во время ожидания информации.

Мой подход заключается в том, чтобы поместить запрос на информацию в метод _DoWork фонового рабочего и использовать ManualResetEvent.Set(), чтобы указать, что информация была обработана. Значение ManaualResetEvent должно быть установлено в методе _RunWorkerCompleted. _RunWorkerCompleted никогда не выполняется.

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.ServiceProcess;
using System.Threading;
using System.Diagnostics;

namespace DemoTest
{

    public partial class Form1 : Form
    {
        List<ServiceController> MyBox1Services;

        ManualResetEvent MyBox1ServicesObtained = new ManualResetEvent(false);


        public Form1()
        {
            InitializeComponent();

        }



        private void button1_Click(object sender, EventArgs e)
        {

            // Use background worker to get the list of services in the background
            BackgroundWorker MyBox1Servicess = new BackgroundWorker();
            MyBox1Servicess.DoWork  = new DoWorkEventHandler(bwGetMyBox1Services_DoWork);
            MyBox1Servicess.RunWorkerCompleted  = new RunWorkerCompletedEventHandler(MyBox1Servicess_RunWorkerCompleted);




            MyBox1Servicess.RunWorkerAsync();

            // Wait until all the services have been obtained before moving on

            MyBox1ServicesObtained.Reset();

            MyBox1ServicesObtained.WaitOne();


            // Update the GUI Here....


        }


        void MyBox1Servicess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                MessageBox.Show("Canceled!");
            }

            else if (!(e.Error == null))
            {
                MessageBox.Show(e.Error.Message);
            }

            else
            {
                Debug.WriteLine("MyBox1Servicess_RunWorkerCompleted");
            }
            MyBox1Services = (List<ServiceController>)e.Resu<
            MyBox1ServicesObtained.Set();
        }


        void bwGetMyBox1Services_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            ServiceController[] allServices;
            List<ServiceController> allServicesList = new List<ServiceController>();

            try
            {
                allServices = ServiceController.GetServices("MyBox1");
                foreach (ServiceController sc in allServices)
                {
                    allServicesList.Add(sc);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            e.Result = allServicesList;
        }

    }
}
  

Ответ №1:

Это потому, что RunWorkerCompleted событие запускается в потоке пользовательского интерфейса, который вы заблокировали в обработчике нажатия кнопки с ManualResetEvent вызовом WaitOne .’

Вместо того, чтобы использовать ManualResetEvent , почему бы просто не обновить ваш графический интерфейс в RunWorkerCompleted обработчике событий?

Комментарии:

1. Да, обработчик нажатия кнопки должен завершиться как можно скорее

2. Спасибо. Фактическое приложение извлекает службы с 10 разных серверов, поэтому я собирался дождаться их завершения, прежде чем двигаться дальше. (10 MannualResetEvents). Я найду альтернативный метод сигнализации. Вероятно, мне следует использовать потоки вместо фонового рабочего (?)

3. @darwin — Bgw инкапсулирует поток. Но вам следует избегать блокирования вашего основного потока (GUI).

4. Кроме того, если вы хотите распараллелить свою работу, я бы заглянул в библиотеку параллельных задач, которая позаботится о большей части этой синхронизации для вас.

5. 1 за выделение ошибки ожидания в обработчике событий пользовательского интерфейса, когда потоки что-то завершают.