sourcegit/src/Models/IpcChannel.cs

104 lines
3.2 KiB
C#

using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Threading.Tasks;
namespace SourceGit.Models
{
public class IpcChannel : IDisposable
{
public bool IsFirstInstance
{
get => _isFirstInstance;
}
public event Action<string> MessageReceived;
public IpcChannel()
{
try
{
_singletoneLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_isFirstInstance = true;
_server = new NamedPipeServerStream(
"SourceGitIPCChannel" + Environment.UserName,
PipeDirection.In,
-1,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous | PipeOptions.CurrentUserOnly);
_cancellationTokenSource = new CancellationTokenSource();
Task.Run(StartServer);
}
catch
{
_isFirstInstance = false;
}
}
public void SendToFirstInstance(string cmd)
{
try
{
using (var client = new NamedPipeClientStream(".", "SourceGitIPCChannel" + Environment.UserName, PipeDirection.Out, PipeOptions.Asynchronous | PipeOptions.CurrentUserOnly))
{
client.Connect(1000);
if (!client.IsConnected)
return;
using (var writer = new StreamWriter(client))
{
writer.WriteLine(cmd);
writer.Flush();
}
if (OperatingSystem.IsWindows())
client.WaitForPipeDrain();
else
Thread.Sleep(1000);
}
}
catch
{
// IGNORE
}
}
public void Dispose()
{
_cancellationTokenSource?.Cancel();
_singletoneLock?.Dispose();
}
private async void StartServer()
{
using var reader = new StreamReader(_server);
while (!_cancellationTokenSource.IsCancellationRequested)
{
try
{
await _server.WaitForConnectionAsync(_cancellationTokenSource.Token);
if (!_cancellationTokenSource.IsCancellationRequested)
{
var line = await reader.ReadToEndAsync(_cancellationTokenSource.Token);
MessageReceived?.Invoke(line?.Trim());
}
_server.Disconnect();
}
catch
{
if (!_cancellationTokenSource.IsCancellationRequested && _server.IsConnected)
_server.Disconnect();
}
}
}
private FileStream _singletoneLock = null;
private bool _isFirstInstance = false;
private NamedPipeServerStream _server = null;
private CancellationTokenSource _cancellationTokenSource = null;
}
}