Как я могу синхронно получить доступ / вызвать объект от нескольких фоновых работников - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть объект в моем основном потоке пользовательского интерфейса, который отправляет последовательные команды в arduino, и мне нужно иметь возможность получить доступ к этому объекту и заставить его отправлять последовательные команды в arduino в порядке их получения от двух отдельных фоновых рабочих.

Я искал и нашел много способов обновить пользовательский интерфейс от нескольких фоновых рабочих, но проблема в том, что большинство решений ориентированы на объекты, которые были разработаны с учетом многопоточности.Т.е. вы можете выполнить «GUIobject.Invoke (и т. Д.)».

        var driver = Periphrials.InitializeArduinoDriver();


        StillMonitor = new BackgroundWorker();
        StillMonitor.WorkerSupportsCancellation = true;
        StillMonitor.DoWork += new DoWorkEventHandler((state, args) =>

        {
        do
            {
                if (StillMonitor.CancellationPending)
                { break; }
                (driver.Send(new DigitalReadRequest(properties.StillLowSwitch)).PinValue.ToString() == "Low")      
            } while (true);
        });

Часть «driver.send ......» - это то, что нужно запустить в главном потоке, но вызвать изнутрифоновые рабочие.

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Если вы используете Backgroundworker-Class, вы можете использовать ProgressChanged-Event.Этот подход не блокирует поток фонового работника при каждом вызове отправки.

var driver = Periphrials.InitializeArduinoDriver();

StillMonitor = new BackgroundWorker();
StillMonitor.WorkerSupportsCancellation = true;
StillMonitor.WorkerReportsProgress = true;
StillMonitor.DoWork += new DoWorkEventHandler((state, args) =>
{
    do
    {
        if (StillMonitor.CancellationPending)
        { 
            break;
        }
        StillMonitor.ReportProgress(0); //Invokes the ProgressChanged Event on the thread the backgroundworker was created on.
    } while (true);
});
StillMonitor.ProgressChanged += (sender, e) => {
     (driver.Send(new DigitalReadRequest(properties.StillLowSwitch)).PinValue.ToString() == "Low")
}

Если поток должен блокироваться при каждом вызове отправки, рассмотрите возможность использования класса Dispatcher (необходимо добавитьссылка на WindowsBase.dll):

using System.Windows.Threading; //WindowsBase.dll

//...

var driver = Periphrials.InitializeArduinoDriver();
Dispatcher driverDispatcher = Dispatcher.CurrentDispatcher; //Gets the Dispatcher for the current Thread (or creates it)

StillMonitor = new BackgroundWorker();
StillMonitor.WorkerSupportsCancellation = true;
StillMonitor.DoWork += new DoWorkEventHandler((state, args) =>
{
    do
    {
        if (StillMonitor.CancellationPending)
        { 
            break;
        }
        driverDispatcher.Invoke(new Action(() => { //Invoke and block the Dispatcher
            (driver.Send(new DigitalReadRequest(properties.StillLowSwitch)).PinValue.ToString() == "Low")  
        }));    
    } while (true);
});
0 голосов
/ 13 февраля 2019

вы можете синхронизировать вызов driver.send с механизмом блокировки, таким как оператор блокировки .

/////class
{
   private readonly object lockObject = new object();
   ....

   ///method
   var driver = Periphrials.InitializeArduinoDriver();

   StillMonitor = new BackgroundWorker();
   StillMonitor.WorkerSupportsCancellation = true;
   StillMonitor.DoWork += new DoWorkEventHandler((state, args) =>
   {
      do
      {
         if (StillMonitor.CancellationPending)
         { break; }
         lock (lockObject)
         {
             //code here will run synchronously
             (driver.Send(new DigitalReadRequest(properties.StillLowSwitch)).PinValue.ToString() == "Low")      
         }
      } while (true);
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...