Requirements
The most important thing will be the speed of each operation as it might be used to control emergency stops and such.
The diagrams you've shown do not inherently translate to performance differences. Pre-compilation code and post-compilation applications are very different in that sense.
What would be a much more impactful decision here, is how you translate your tag name ("qw450") into a set of instructions. That means you've got a mapping, which is stored somewhere, and where it is stored is going to be key to squeezing things for performance. Where the memory footprint allows it, in-memory data storage is usually the most performant.
Another impactful decision here is how this communication is going to happen. Since you call it a "new application", I suspect it's going to have its own runtime, as opposed to the old DLL which would just be included in the runtime of the WPF application itself? Then you need to really consider where this second runtime is situated relative to the frontend.
Is it the same machine? The same local network? An internet connection? The performance of your communication medium is always going to significantly impact the performance of your application.
Note that running things on the same machine isn't always the most performant option, in cases where you need more CPU power than your machines can provide. This is why most companies tend to separate their database servers from their application servers, as the network delay is smaller than the impact on the CPU of a machine that is both a database server and application server.
Related to this is the question whether you have multiple frontends active at the same time or not. If you do, that adds more of a reason to consider whether your second application should be hosted on a shared remote resource, or on each local machine that also runs a frontend.
Which option?
Right now, this makes the question very hard to answer. You've given us three options to choose from (or a fourth one of our own making), but the criteria for deciding between these options (performance) aren't meaningfully affected by these different options. So it's anyone's guess as to what will actually work for you best.
So instead, I'll give you a quick rundown of what each of your options will entail.
Option 1
This is the simplest way to do it. Your new application effectively wraps the old DLL and becomes its new public interface, to be consumed by your frontend.
It's simple and straightforward. Your frontend developer only needs to know your new application's interface, which in turn provides everything the frontend will ever need.
But it comes with one notable drawback: your wrapper will need to handle/expose every interaction between your frontend and your DLL.
The reason I mention this is because of the communication where the IO server contacts the frontend (instead of the other way around). You mention that this needs to happen, but you don't actually mention that your new application should do anything different than what the DLL already provides.
If that is indeed the case, this means that your new application is going to have to expose the same feature without really changing it, leading to a bit of passthrough code that adds no real value. It's not really a dramatic issue, but it's a bit of extra work with no real benefit.
Option 3
Sorry for changing the order of the options but it helps with the explanation.
Here, you've ensured that your frontend has choice. It can take the old path, or it can opt to take the new path. A frontend developer is free to choose whichever path they want.
The benefit here is that you don't have the issue from option 1. You don't need to make passthrough wrappers, the frontend can just access the DLL directly. That will save you some effort in developing the new application as you don't need to spend time writing those wrappers.
The drawback here is a matter of complexity. With choice comes the responsibility of needing to make the right choice. Your frontend developer now needs to know both the new application and the old DLL, and needs to make their own informed decision.
Whether that's good or not very much depends on how beneficial it is to bypass your new application or not.
While you may save time on not having to write those wrappers now, it's possible that in the future, your IO-to-WPF communication will need more bells and whistles, and then you'll have to migrate it to your new application. This means that the frontend needs to change the path it chooses, no longer using the old DLL.
For some added complexity, consider if only some of the IO-to-WPF communication migrates to the new application, and some of it remains untouched. Now, your frontend developers really need to evaluate when to use your new application, and when to use your old DLL directly.
The size of this drawback depends on many factors. how liable features are to change, how many features there are, how heavily you need to defend against the frontend bypassing your new application features, ....
In short, this option can streamline the development effort of the new application, but it puts an additional cognitive load on the frontend developers (by forcing them to choose between two options and ensuring they always make the right choice).
Whether or not the benefit outweighs the drawback, is very contextual and a matter of risk assessment.
Option 2
The one big difference here is that you've ensured that your new application is part of the same runtime of the frontend. As I mentioned before, though you'd usually expect this to be more performant than by separating the runtimes across network machines, you also have to consider if the local machine has enough CPU/memory to be able to run both the frontend and new application at the same time.
I would suspect so, but that's just a guess. If this is a highly trafficked scenario (which IO servers tend to be), your frontend may be a very intense application if it visualizes real-time data, and you may not want to see any hiccups (in the UI) when a complex bit of calculation logic in your "new application" is encountered.
This is something you have to decide for yourself, based on your frontend's performance requirements and the hardware you're working with.
In regards to the development benefits/drawbacks mentioned before, you can go either way with this:
- If your "DAL Layer" acts as the sole point of contact to the old DLL, and the frontend should not access the old DLL directly, then this is the same as option 1. The same reasoning applies.
- If your "DAL Layer" is an optional layer and the frontend is still able to access the old DLL directly, then this is the same as option 3. The same reasoning applies.