1

What can I do for use multiple threads in .Net Core hosted BackgroundService ?

Hi, I am building a service for multiple modbus clients. I am using .net core worker service template.

I have a BackgroundService Service named InitializeServices. And this is ExecuteAsync method in the Service.

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    devices = mysqlManager.GetDevices();
    devices.ForEach(x => x.InitializeDevice());
    _exchangeService.SetTags(devices.SelectMany(x => x.ReadTags).ToList());
    devices.ForEach(x => x.Client.InitializeClient());
            
    foreach (var item in devices)
    {        
        Thread thread = new Thread(item.Client.Run);
        thread.Start();
    }

    while (!stoppingToken.IsCancellationRequested)
    {
        Thread.Sleep(10);
        _exchangeService.InsertReadingTagsToDatabase();
    }
}

as u see devices has client classes and client class has run method like this;

while (true)
{
    try
    {
        using (TcpClient client = new TcpClient())
        {
            client.ReceiveTimeout = this.device.RequestTimeout;
            client.SendTimeout = this.device.RequestTimeout;
            client.SendBufferSize = 100024;
            client.ReceiveBufferSize = 100000;
            client.Client.ReceiveTimeout = this.device.RequestTimeout;
            client.Client.SendTimeout = this.device.RequestTimeout;
            client.Client.SendBufferSize = 100024;
            client.Client.ReceiveBufferSize = 100000;

            if (client.ConnectAsync(ipAdress, portNumber).Wait(this.device.ConnectionTimeout))
            {
                this.device.ReadTags.FirstOrDefault(x => x.Name == "_NoError").Value = 1;
                var factory = new ModbusFactory();
                IModbusMaster master = factory.CreateMaster(client);
                ReadWordsFromDriverServer(master);
                SyncTagsFromRegisters();
                //WriteTagsToDatabase();
                //Console.WriteLine(words.Length);
            }
            else
            {
                this.device.ReadTags.FirstOrDefault(x => x.Name == "_NoError").Value = 0;
                this.device.ReadTags.FirstOrDefault(x => x.Name == "_NoError").LastReadTime = DateTime.Now;
            }
        }
    }
    catch (Exception ex)
    {}
    Thread.Sleep(100);
}

My device list count is nearly 700. It means I have 700 client objects and need 700 threads. There must be 700 clients that run periodically but should not keep each other waiting.

In this code I tried but its waiting for each other. What can I do about this or what is wrong in this process? Thanks in advance

refa
  • 11
  • 3
  • 2
    use asynchronous programming. create and await tasks instead of spawning _much_ more threads than you have cpu cores. and use `await` instead of `.Wait()` – Franz Gleichmann May 26 '23 at 18:22
  • @FranzGleichmann Hello my friend, from here I understand that I need to make all my working methods async in while. Is it true? – refa May 26 '23 at 20:36
  • Yes that's exactly what they're saying. Do not use `.Wait`, do not use `Thread.Sleep`, do not block synchronously. Wit tasks you can use your threads much much more efficiently, you might only need a couple of threads to handle 700 clients. – Charlieface May 28 '23 at 02:12
  • Spinning up a single thread consumes at least 1MB of RAM. 700 threads is 0.7GB. Then you're hoping that the run-time can effectively run those 700 threads on a 8 core machine. – Enigmativity May 30 '23 at 11:38

0 Answers0