So using callbacks is certainly one way of doing this. However, the callback channel can timeout and so you'll need a way of automatically reconnecting. If you want to continue down this route then you're looking good understanding-wise.
In my opinion, a simpler (and therefore superior) solution is to use netMsmqBinding, host the service in the WPF app, and then have the windows service consume it. This has the benefit that it's more reliable than duplex communication as it relies on one way calls, and easier to implement.
Additionally the windows service will still be able to send notifications to the WPF app even if the WPF is unavailable - messages will simply queue up until the WPF comes back online. (This may or may not be desirable.)
You would need to have msmq enabled on both machines, and for maximum reliability use transactional queues with DTC.
if I wanted to be able to send data from the client app to the serial
port (the Windows service would still handle the IO), would I have to
implement another WCF service
In this instance yes you would have to configure a service on the windows service which exposed an operation for the WPF to call into. This would need to be defined separately to the one used for notifications, and could just use http/tcp as a transport rather than message queues, as this sounds like a synchronous operation.
Should I define the WCF service inside the WPF project and not as a
stand alone DLL?
The WPF project is the host process for the WCF service. From this perspective it makes no difference if you define the service as a standalone assembly or within the WPF app, you should be able to spin up a ServiceHost
instance within your WPF app which will expose the service.
Despite it making little difference where you define your service code to the runtime hosting of the service, as best-practice I would always try to define your actual service implementation as a separate assembly, to keep things which are logically different in a different place.
how am I supposed to consume the data from the WPF application: the
Windows service will call the WCF service and send the data, from here
I would need to retrieve that data that is hold somewhere
So my understanding was that your original plan was to host the WCF service in the windows service which reads data from a serial port.
The WPF service would then call the WCF service and the WCF service would store the callback delegate for the WPF service, effectively like a subscription.
When data arrived at the serial port the WCF service would then invoke the callback channel and feed data back to the WPF service.
My suggestion was to replace this with a queue-based approach, where you would host the service in the WPF app, and have the windows service simply call the WCF service when data arrived on the serial port.
Then you asked about also having the WPF app call the windows service to pass data across, and I said that you should host a separate service in the windows service in order to expose an endpoint for the WPF app to call. When the WPF app made a call and passed data into the WCF service, this data could then be made available to the windows application which talks to the serial port.
Are you now asking how to allow data passed in on the call from the WPF app to the windows service-hosted WCF app to be available to the windows service? If so then please read my post here, which details how to pass data from an instance of a WCF service to the app domain which is running the ServiceHost instance.