## 1. Use background
Developing a single-process project of WPF, using the MongoDB database in the project, requires connecting multiple different database instances. In addition, the project framework uses event aggregator to manage notification calls between modules, and implements a` based on `NetMQ`. ZeroMQPublisher` and ZeroMQSubscriber`.
**Event Aggregator Service Implementation Solution**:
* `ZeroMQPublisher` will listen to a port of the local address when it starts (for example `tcp://*:5866`)
* When starting `ZeroMQSubscriber`, you need to connect to the NetMQ server (for example: `tcp://127.0.0.1:5866`)
**Implementation solution for starting a database instance**:
In the C# code, start ````````````--dbpath```--port```--replSet``--logpath`, etc.). This logic is called when the application starts.
* The specific implementation code snippet is as follows:
<!---->
var startInfo = new ProcessStartInfo
{
FileName = processName,
Arguments = $"--dbpath \"{}\" --port {} --replSet {} " +
$"--logpath {(, "")} --logappend",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
// Specify the encoding used to read the standard output stream. Specifying as UTF8 ensures that the output is read correctly
StandardOutputEncoding = Encoding.UTF8,
// Specify the encoding used to read the standard error stream. Likewise, specifying as UTF8 ensures that the error output is read correctly
StandardErrorEncoding = Encoding.UTF8
};
var _mongoProcess = new Process { StartInfo = startInfo };
_mongoProcess.Start();
// Subscribe to output and error events
_mongoProcess.OutputDataReceived += (sender, e) =>
{
if (!())
{
outputMsgCallback?.Invoke("MongoDB output: " + );
}
};
_mongoProcess.ErrorDataReceived += (sender, e) =>
{
if (!())
{
outputMsgCallback?.Invoke("MongoDB error: " + );
}
};
_mongoProcess.BeginOutputReadLine();
_mongoProcess.BeginErrorReadLine();
Note: In order to realize that the database instance can still be connected after the WPF program exits, the above `Process` resource was not cleared when exiting the program.
* Implementation effect:
* a. Multiple different `mongo db` database instances can be started by configuration;
* b. You can redirect the logs started by the `mongo db` database instance and record them through the definition of `outputMsgCallback` (there is already a specified --logpath, but you don't need redirected output information)
## 2. Problem phenomenon
* After the `WPF` program exits, start the program again and the error message will be prompted as follows:
<!---->
Internal exception:
SocketException: Usually, each socket address (protocol/network address/port) is only allowed to be used once.
* Check port occupancy, execute `netstat -ano | finstr :5866`, and return the following information:
<!---->
TCP 0.0.0.0:5866 0.0.0.0:0 LISTENING 46064
TCP 127.0.0.1:3172 127.0.0.1:5866 ESTABLISHED 46064
TCP 127.0.0.1:5866 127.0.0.1:3172 ESTABLISHED 46064
Query the corresponding process (`tasklist /FI "PID eq 46064" `) through the process `id 46064` shown above, and the corresponding process information cannot be found.

## 3. Causes of the problem and analysis
1. Check the implementation logic and find that when the application exits, the corresponding `NetMQ`' Dispose` release logic has been called;
2. Optimization attempt: Execute the `DiscConnect` logic first before releasing the connected resources will not solve the problem;
3. Tool analysis `[TCPView](/en-us/sysinternals/downloads/tcpview?spm=5aebb161.543df828.0.0.737f7038lsFU2W)`
Use the `TCPView` tool to see the corresponding 3 `tcp` connection information, but the associated actual process information cannot be viewed, and the problem cannot be solved.
4\. Use the `[ProcessExplorer](/en-us/sysinternals/downloads/process-explorer)` tool to view the process information, select ``, view the properties, and find that it will show that `Parent` is the WPF application process above.


After the two `kill`, the above port occupation problem will no longer occur. Therefore, the main reason for the problem is that the ```launched database instance process and the main process are associated, and the root cause is that the `Process` startup process is not isolated from the main process.
## 4. Solution
1. Modify the process startup method:
<!---->
var startInfo = new ProcessStartInfo
{
FileName = processName,
Arguments = $"--dbpath \"{}\" --port {} --replSet {} " +
$"--logpath {(, "")} --logappend",
UseShellExecute = true,
CreateNoWindow = true,
WindowStyle =
};
* Start the process through `Shell` (`UseShellExecute = true`), rather than directly started by the current application;
* Hide the startup `Shell` window (`WindowStyle = `);