Threading, C#

Markus Freitag 3,791 Reputation points
2023-06-10T07:23:40.0166667+00:00

Hello,

START ORDER produce 1000 products
        Loop
            ProductIn
            ProcessStart
            ProductOut 
            |-------------|------------------------|
            IN             START                   OUT
             PLC enables mechanical transport. Depending on the state, I receive an event that I simulate via a button.
        END


Buttons
   OrderStart
        In  
        START
        End   
   OrderEnd

Thanks for the answer. Did you understand my problem? You need to develop a good concept. With threads, timer or task. What would you favor? I would provide the logging with SeriLog.

Is not clear what you have changed, what you mean. I am looking for a good concept, an example.

I would like to ask the experts here, as I lack experience in this field. Threading is a difficult task. Oce again the summary.

I have an order with up to 1000 products to be manufactured. They are manufactured on one machine. The machine transports the product, the PLC sends the states to the C# application.

    |-------------|------------------------|
    IN            START                    OUT 

It would be so nice if you could help me with sample code. I think task or thread are the better approaches than via timer

See also the picture. 2023-06-09-OverView

Developer technologies .NET Other
Developer technologies C#
{count} votes

3 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2023-06-10T17:33:37.0866667+00:00

    The question is how do you get the sensor data? How are events delivered? Are you using an sdk supplied by the PCL provider?

    generally you would use a state machine and async or polling events. Async can be singe threaded or require async threads. Both the network and serial I/O support async without threads.

    if the controller has a UI then you may want a worker thread to do the processing so the ui is free.


  2. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2023-06-11T23:30:55.27+00:00

    you need to write the PCL communication layer first and defines its api. say async process with async callbacks. calling Run(), opens the socket to the PLC, does any initialization, parses tcp messages, and does the event callback for the message.

    pcl comm

    public class PclComm
    {
        public PclComm(PclComOptions options)
        {
            ...
        }
        public async Task Run(PclProcessData data)
        {
            var socket = await OpenSocket();
            var done = false;
    
            await socket.Send(startMessage);
            while (!done)
            {
                var response = await socket.GetNextMessage();
                await response switch  
                {
                    InResponse => _onInCallback(),
                    StartResponse => _onStartCallback(),
                    OutResponse => async () => 
                    {
                       await _onOutCallback();
                       // check process count
                       if (++_processCount >= _requestedCount)
                       {
                           await socket.Shutdown();
                           done = true;
                       }
                    },
                };
            }  
        }
    }
    

    event code:

    private void ProcessButton_Click(object sender, RoutedEventArgs e)
    {
        buttonProcess.Disabled = true;
    
        // start process thread;
        Process(); 
    }
    
    void ReportStatusToUi(string status)
    {
       Application.Current.Dispatcher.Invoke(new Action(() => 
       {  
           lblStatus.Content = status;
       }));
    }
    
    async Task Process()
    {
         // create plc communication object
         _plcComm = new PclComm(
         {
            OnIn,
            OnStart,
            OnOut    
         });
    
         // get process data 
         var data = await GetData();
    
         // run 
         await _plcComm.Run(data);
    
         // all done
         _plcComm = null;
         Application.Current.Dispatcher.Invoke(new Action(() => 
         {  
           buttonProcess.Disabled = false;
         }));
    }
    
    async Task OnIn()
    {
       ...
       ReportStatusToUi("in");
    }
    async Task OnStart()
    {
       ...
       ReportStatusToUi("start");
    }
    async Task OnOut()
    {
       ...
       ReportStatusToUi("out");
    }
    
    

  3. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2023-06-12T20:04:09.1233333+00:00

    if a sync method calls an async, it just doesn't wait. the async call returns a thread, which you could later access. say you wanted to kill after a timeout.

    I passed the event callbacks on the constructor, but you can expose an event delegate instead:

    pclComm.OnStart += OnStart;

    you haven't defined the communication protocol of the PCL device. is it a tcp/ip stream or UDP? how does it send events? does you app poll? does it just send unsolicited messages? is there an ack protocol? What are the time time requirements?

    the threading is trivial. All your work will be in PCL interface. here is a simplified explanation the protocol used for Siemens S7 PLC's:

    http://gmiru.com/article/s7comm-part2/

    simple c# s7:

    https://github.com/mycroes/Sally7

    it appears you need extensive knowledge of the memory structure of the PCL device.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.