如何从多个后台工作人员同步访问/调用对象

时间:2019-02-13 13:16:23

标签: c# multithreading queue

我的主UI线程上有一个对象,该对象将串行命令发送到arduino,我需要能够访问该对象,并使其按从两个单独的后台工作程序中接收到的顺序将串行命令发送到arduino

我四处寻找并发现了许多方法来更新来自多个后台工作人员的UI,但问题是大多数解决方案都针对考虑了多线程设计的对象。即您可以执行“ GUIobject.Invoke(etc)”。

        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 :(得分:1)

如果您正在使用Backgroundworker-Class,则可以使用ProgressChanged-Event。这种方法不会在每次发送调用时都阻塞backgroundworker线程。

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-Class(您需要添加对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);
});

答案 1 :(得分:0)

您可以使用诸如lock-statement之类的锁定机制来同步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);
  });