gpt4 book ai didi

C# dot net core 单实例应用程序将参数传递给第一个实例

转载 作者:行者123 更新时间:2023-12-03 22:43:57 27 4
gpt4 key购买 nike

最近我决定迁移我用 C# 编写的 WPF Windows 桌面应用程序之一,目标是 。 .NET Framework 4.5 到 最新 .NET Core 3.1 .一切都很好,直到我不得不添加对单实例应用程序的支持,同时能够将任何参数从第二个实例传递到第一个正在运行的实例。我之前对单实例应用程序的 WPF 实现是使用 System.Runtime.Remoting 在 .NET Core 中不可用.因此我不得不做一些新的事情。下面是我想出的实现。它工作得很好,但我觉得它可以改进。请随时讨论和改进建议的解决方案。
我创建了一个 SingleInstanceService ,它使用信号量来指示它是否是第一个实例。如果它是第一个实例,我创建一个 TcpListener 并无限期地等待从第二个实例传递的任何参数。如果启动了第二个实例,那么我将第二个实例的参数发送到第一个监听实例,然后退出第二个实例。

internal class SingleInstanceService
{
internal Action<string[]> OnArgumentsReceived;

internal bool IsFirstInstance()
{
if (Semaphore.TryOpenExisting(semaphoreName, out semaphore))
{
Task.Run(() => { SendArguments(); Environment.Exit(0); });
return false;
}
else
{
semaphore = new Semaphore(0, 1, semaphoreName);
Task.Run(() => ListenForArguments());
return true;
}
}

private void ListenForArguments()
{
TcpListener tcpListener = new TcpListener(IPAddress.Parse(localHost), localPort);
try
{
tcpListener.Start();
while (true)
{
TcpClient client = tcpListener.AcceptTcpClient();
Task.Run(() => ReceivedMessage(client));
}
}
catch (SocketException ex)
{
Log.Error(ex);
tcpListener.Stop();
}
}

private void ReceivedMessage(TcpClient tcpClient)
{
try
{
using (NetworkStream networkStream = tcpClient?.GetStream())
{
string data = null;
byte[] bytes = new byte[256];
int bytesCount;
while ((bytesCount = networkStream.Read(bytes, 0, bytes.Length)) != 0)
{
data += Encoding.UTF8.GetString(bytes, 0, bytesCount);
}
OnArgumentsReceived(data.Split(' '));
}
}
catch (Exception ex)
{
Log.Error(ex);
}
}

private void SendArguments()
{
try
{
using (TcpClient tcpClient = new TcpClient(localHost, localPort))
{
using (NetworkStream networkStream = tcpClient.GetStream())
{
byte[] data = Encoding.UTF8.GetBytes(string.Join(" ", Environment.GetCommandLineArgs()));
networkStream.Write(data, 0, data.Length);
}
}
}
catch (Exception ex)
{
Log.Error(ex);
}
}

private Semaphore semaphore;
private string semaphoreName = $"Global\\{Environment.MachineName}-myAppName{Assembly.GetExecutingAssembly().GetName().Version}-sid{Process.GetCurrentProcess().SessionId}";
private string localHost = "127.0.0.1";
private int localPort = 19191;
}
然后在 App.xaml.cs 中,我有以下代码:
protected override void OnStartup(StartupEventArgs e)
{
SingleInstanceService singleInstanceService = new SingleInstanceService();

if (singleInstanceService.IsFirstInstance())
{
singleInstanceService.OnArgumentsReceived += OnArgumentsReceived;
// Some other calls
}
base.OnStartup(e);
}

private void OnArgumentsReceived(string[] args)
{
// ProcessCommandLineArgs(args);
}
请随意讨论这个主题,我认为这是 Windows 桌面开发人员中非常常见的用例。谢谢你。

最佳答案

使用依赖注入(inject)。您将需要定义一个接口(interface),然后实现该接口(interface)。在启动代码中,您需要将接口(interface)及其实现添加为单例服务。

在您的实现构造函数中,您可以放置​​您只想运行一次的代码。这将持续对象的生命周期。

还有其他类型的注入(inject), transient 注入(inject)和作用域注入(inject),但对于您的用例,您可能只需要单例。

程序.cs

using System;
using Microsoft.Extensions.DependencyInjection;

namespace example
{
class Program
{
static void Main(string[] args)
{
// create service collection
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);

var serviceProvider = serviceCollection.BuildServiceProvider();

serviceProvider.GetService<Startup>().Run();
}

private static void ConfigureServices(IServiceCollection serviceCollection)
{
// add services
serviceCollection.AddTransient<IMyService, MyService>();

serviceCollection.AddTransient<Startup>();
}
}
}

启动.cs
namespace example
{
public class Startup
{
private readonly IMyService _myService;
public Startup(IMyService myService)
{
_myService = myService;
}

public void Run()
{
_myService.MyMethod();
}

}
}

互动
namespace example
{
public interface IMyService
{
void MyMethod();
}
}

服务实现
 namespace example
{
public class MyService : IMyService
{
public MyService()
{
// on signleton service this only gets invoked once
}

public void MyMethod()
{
// your imolmentation here
}
}
}

一些网上引用:
https://dzone.com/articles/dependency-injection-in-net-core-console-applicati

https://code-maze.com/dependency-inversion-principle/

关于C# dot net core 单实例应用程序将参数传递给第一个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59706160/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com