serviceblazor-server-siderazor-pageslivecyclic

My Blazor server side app's scoped service is reading a process value cyclic from a remote PLC. How can I show this value live on my razor page?


In my Blazor server side app I have a scoped service that is reading a process value from a remote PLC, cyclic. With my code below I try to show the value live on my razor page. But getting just one value shown (not actualized, although the value is dynamically changing). It seems that the data is not transfered correctly from the service to the razor page. What could be the problem:

My Scoped service code: (Data_reader_service)

   public void read_data_cyclic()
   {
      try
      {         
      
      for(int y=0; y<10; y++)
      {
        //here I am reading process value from a remote PLC cyclic to the var. item_value. I can verify that the values are read by writing to a log file.
        using (StreamWriter sw2 = File.AppendText(log_path))
        {
          sw2.WriteLine("val-"+y+":"+item_value+" "+Convert.ToString(DateTime.Now));
        }                                           
        // here I pass the values to the event handler             
        Pass_item(item_value);            
        Thread.Sleep(1000);
        // next cycle data reading
      }
      catch
      {
          //Error handling;
      }
    }

    public string Pass_item(string new_item)
    {            
        Item_Changed?.Invoke(Item_Changed, new_item);
        return new_item;
    }

    public event EventHandler<string> Item_Changed;

My razor page's code (When I click the button, the service shall start to read data)

   @inject Data_reader_service Data_reader_service
   <table>
   <tr>        
      <td>
        <button @onclick="call_read_data_service">
        </button>
      </td>
      <td>@item_value</td>
   </tr>
   </table>

My razor page's cs code:

    public async Task call_read_data_service()
    { 
      await Task.Run(() => Data_reader_service.read_data_cyclic());
      //this time I have set for to be sure that the service has connected to remote PLC and started to read data
      Thread.Sleep(5000);
      Data_reader_service.Item_Changed += Item_Changed;
    }

    string item_value;
    private async void Item_Changed(object sender, string new_item)
    {
        await InvokeAsync(() =>
        {
            // Set the local counter variable
            item_value = new_item;
            // Tell Blazor to rewrite the DOM
            StateHasChanged();
        });
    }  

Solution

  • I noticed that I have checked just once for value change in my razor.cs code. I changed my razor.cs code like following, and it worked:

    // I added a Timer
    public System.Timers.Timer timer1 = new System.Timers.Timer();
    
    public async Task call_read_data_service()
    { 
    
      timer1.Elapsed += new ElapsedEventHandler(OnTimedEvent1);
      timer1.Interval = 1000;
      timer1.Enabled = true;
    
      await Task.Run(() => Data_reader_service.read_data_cyclic());  
    }
    
    // Checked the Item_Changed event every second
    public void OnTimedEvent1(object source, ElapsedEventArgs e)
    {
        Data_reader_service.Item_Changed += Item_Changed;
    }
    
    string item_value;
    private async void Item_Changed(object sender, string new_item)
    {
        await InvokeAsync(() =>
        {
            // Set the local counter variable
            item_value = new_item;
            // Tell Blazor to rewrite the DOM
            StateHasChanged();
        });
    }