0

I could us some help getting the WriteMultipleCoilsAsync task to run. I'm getting the error message Cannot assign void to an implicitly-typed variable on the Task.Run statement. I need to capture the response message from WriteMultipleCoilsAsync.

Here the code:

  private async void btnWriteMultipleCoils_Click(object? sender, EventArgs e)
    {
        string discretes = "true,false,true";
        bool[] diarray = Array.ConvertAll(discretes.Split(','), bool.Parse);
        var response = await Task.Run(() => master.WriteMultipleCoilsAsync(0, diarray));
        await Task.CompletedTask;
    }

Here is the WriteMultipleCoilsAsync task:

    public Task WriteMultipleCoilsAsync(ushort startAddress, bool[] data)
    {
        return WriteMultipleCoilsAsync(0, startAddress, data);
    }

Here is the WriteMultipleCoilsAsync task:

public Task WriteMultipleCoilsAsync(byte slaveAddress, ushort startAddress, bool[] data)
    {
        ValidateData("data", data, 1968);
        WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(slaveAddress, startAddress, new DiscreteCollection(data));
        return PerformWriteRequestAsync<WriteMultipleCoilsResponse>(request);
    }

Here is the PerformWriteRequestAsync Task:

        private Task PerformWriteRequestAsync<T>(IModbusMessage request) where T : IModbusMessage, new()
    {
        return Task.Factory.StartNew(() => base.Transport.UnicastMessage<T>(request));
    }

Here is the UnicastMessage method:

 internal virtual T UnicastMessage<T>(IModbusMessage message) where T : IModbusMessage, new()
    {
        IModbusMessage modbusMessage = null;
        int num = 1;
        bool flag = false;
        do
        {
            try
            {
                lock (_syncLock)
                {
                    Write(message);
                    bool flag2;
                    do
                    {
                        flag2 = false;
                        modbusMessage = ReadResponse<T>();
                        SlaveExceptionResponse slaveExceptionResponse = modbusMessage as SlaveExceptionResponse;
                        if (slaveExceptionResponse != null)
                        {
                            flag2 = slaveExceptionResponse.SlaveExceptionCode == 5;
                            if (!flag2)
                            {
                                throw new SlaveException(slaveExceptionResponse);
                            }

                            Sleep(WaitToRetryMilliseconds);
                        }
                        else if (ShouldRetryResponse(message, modbusMessage))
                        {
                            flag2 = true;
                        }
                    }
                    while (flag2);
                }

                ValidateResponse(message, modbusMessage);
                flag = true;
            }
            catch (SlaveException ex)
            {
                if (ex.SlaveExceptionCode != 6)
                {
                    throw;
                }

                if (SlaveBusyUsesRetryCount && num++ > _retries)
                {
                    throw;
                }

                Sleep(WaitToRetryMilliseconds);
            }
            catch (Exception ex2)
            {
                if (ex2 is FormatException || ex2 is NotImplementedException || ex2 is TimeoutException || ex2 is IOException)
                {
                    if (num++ > _retries)
                    {
                        throw;
                    }

                    continue;
                }

                throw;
            }
        }
        while (!flag);
        return (T)modbusMessage;
    }
Paul
  • 93
  • 2
  • 11
  • 2
    What happens if you remove the `var response = ` part? – Theodor Zoulias Nov 16 '22 at 22:47
  • I'm running the async version in order to capture the response messages from that Modbus slave. I can get it to work without getting the response message, but in this case that does work for me. It does successfully run the task without the var response =. But I need the response. – Paul Nov 16 '22 at 23:24
  • Then your async methods should return a `Task`, not a naked `Task`. Could you replace the `var` with the actual type of the response? – Theodor Zoulias Nov 16 '22 at 23:38
  • How do I identify the correct type the Task returns? WriteMultipleCoilsAsync(ushort startAddress, bool[] data) { return WriteMultipleCoilsAsync(0, startAddress, data); } – Paul Nov 17 '22 at 00:04
  • Could you edit the question and include the signature of the `PerformWriteRequestAsync` method? – Theodor Zoulias Nov 17 '22 at 00:13
  • The PerformWriteRequestAsync task has been added – Paul Nov 17 '22 at 00:18
  • Could you also include the signature of the `UnicastMessage` method? I hope this one reveals the return type. – Theodor Zoulias Nov 17 '22 at 00:27
  • Okay, I added the UnicasMessage method. – Paul Nov 17 '22 at 00:42
  • I tried Task response = await Task.Run(() => master.WriteMultipleCoilsAsync(0, diarray)); but same error message – Paul Nov 17 '22 at 00:45
  • Try changing the return type of the three methods `WriteMultipleCoilsAsync(2 args)`, `WriteMultipleCoilsAsync(3 args)`, and `PerformWriteRequestAsync` from `Task` to `Task`, and see what happens. – Theodor Zoulias Nov 17 '22 at 00:54
  • The methods are part of the NModbus NuGet package I installed and are locked. Would have to figure out how to unlock to update. You don't think it's working out of the box? I have been unable to find any examples on the internet of anyone using the WriteMultipleCoilsAsync method. The tool I'm working with echo back response message to the Modbus requests. That why I need them – Paul Nov 17 '22 at 01:09
  • 1
    I have no idea what this library does and how well it does it, but I can definitely tell you that the method [`ModbusMaster.PerformWriteRequestAsync`](https://github.com/NModbus/NModbus/blob/04a54c8ddc131e4708bcb0a14871c941b3402243/NModbus/Device/ModbusMaster.cs#L474) violates [the guideline](https://devblogs.microsoft.com/pfxteam/should-i-expose-asynchronous-wrappers-for-synchronous-methods/) about not exposing asynchronous wrappers for synchronous methods, as well as the [CA2008](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2008) guideline. – Theodor Zoulias Nov 17 '22 at 02:38
  • 1
    I posted this information to the NModbus GitHub (Issues) site. I inquired on how to make the recommended changes, so that we can test to see if the changes fix the problem. I hope that your okay that I referenced this post in the GitHub NModbus Issues post. I appreciate your help with the issue. – Paul Nov 17 '22 at 14:34
  • Paul yes, it's OK, feel free to link to any of my comments. :-) – Theodor Zoulias Nov 17 '22 at 15:01

0 Answers0