mirror of
https://github.com/netchx/netch.git
synced 2026-03-14 17:43:18 +08:00
Update ServerHelper.cs
Extract and Refactor DelayTestHelper
This commit is contained in:
@@ -78,7 +78,7 @@ namespace Netch.Forms
|
||||
|
||||
LoadServers();
|
||||
SelectLastServer();
|
||||
ServerHelper.DelayTestHelper.UpdateInterval();
|
||||
DelayTestHelper.UpdateTick(true);
|
||||
|
||||
ModeHelper.InitWatcher();
|
||||
ModeHelper.Load();
|
||||
@@ -592,7 +592,7 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
if (oldSettings.DetectionTick != Global.Settings.DetectionTick)
|
||||
ServerHelper.DelayTestHelper.UpdateInterval();
|
||||
DelayTestHelper.UpdateTick(true);
|
||||
|
||||
if (oldSettings.ProfileCount != Global.Settings.ProfileCount)
|
||||
LoadProfiles();
|
||||
@@ -663,7 +663,7 @@ namespace Netch.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
await ServerHelper.DelayTestHelper.TestAllDelayAsync();
|
||||
await DelayTestHelper.PerformTestAsync(true);
|
||||
Enable();
|
||||
}
|
||||
}
|
||||
@@ -995,7 +995,7 @@ namespace Netch.Forms
|
||||
|
||||
_state = value;
|
||||
|
||||
ServerHelper.DelayTestHelper.Enabled = IsWaiting(_state);
|
||||
DelayTestHelper.Enabled = IsWaiting(_state);
|
||||
|
||||
StatusText();
|
||||
switch (value)
|
||||
@@ -1057,14 +1057,11 @@ namespace Netch.Forms
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
private bool IsWaiting()
|
||||
{
|
||||
return State == State.Waiting || State == State.Stopped;
|
||||
}
|
||||
private bool IsWaiting() => IsWaiting(_state);
|
||||
|
||||
private static bool IsWaiting(State state)
|
||||
{
|
||||
return state == State.Waiting || state == State.Stopped;
|
||||
return state is State.Waiting or State.Stopped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1253,7 +1250,7 @@ namespace Netch.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
State = State.Terminating;
|
||||
// State = State.Terminating;
|
||||
NotifyIcon.Visible = false;
|
||||
Hide();
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Netch.Forms
|
||||
|
||||
BindTextBox<int>(ProfileCountTextBox, i => i > -1, i => Global.Settings.ProfileCount = i, Global.Settings.ProfileCount);
|
||||
BindTextBox<int>(DetectionTickTextBox,
|
||||
i => ServerHelper.DelayTestHelper.Range.InRange(i),
|
||||
i => DelayTestHelper.Range.InRange(i),
|
||||
i => Global.Settings.DetectionTick = i,
|
||||
Global.Settings.DetectionTick);
|
||||
|
||||
|
||||
@@ -43,11 +43,7 @@ namespace Netch.Models
|
||||
/// <summary>
|
||||
/// 代理类型
|
||||
/// </summary>
|
||||
public virtual string Type { get; } = string.Empty;
|
||||
|
||||
[JsonExtensionData]
|
||||
// ReSharper disable once CollectionNeverUpdated.Global
|
||||
public Dictionary<string, object> ExtensionData { get; set; } = new();
|
||||
public abstract string Type { get; }
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
@@ -62,7 +58,7 @@ namespace Netch.Models
|
||||
{
|
||||
var remark = string.IsNullOrWhiteSpace(Remark) ? $"{Hostname}:{Port}" : Remark;
|
||||
|
||||
var shortName = Type.IsNullOrEmpty() ? "WTF" : ServerHelper.GetUtilByTypeName(Type).ShortName;
|
||||
var shortName = ServerHelper.GetUtilByTypeName(Type).ShortName;
|
||||
|
||||
return $"[{shortName}][{Group}] {remark}";
|
||||
}
|
||||
|
||||
107
Netch/Utils/DelayTestHelper.cs
Normal file
107
Netch/Utils/DelayTestHelper.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Models;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class DelayTestHelper
|
||||
{
|
||||
private static readonly Timer Timer;
|
||||
|
||||
private static readonly SemaphoreSlim Lock = new(1, 1);
|
||||
|
||||
private static readonly SemaphoreSlim PoolLock = new(16, 16);
|
||||
|
||||
public static readonly NumberRange Range = new(0, int.MaxValue / 1000);
|
||||
|
||||
private static bool _enabled = true;
|
||||
|
||||
static DelayTestHelper()
|
||||
{
|
||||
Timer = new Timer
|
||||
{
|
||||
Interval = 10000,
|
||||
AutoReset = true
|
||||
};
|
||||
|
||||
Timer.Elapsed += (_, _) => PerformTestAsync().Forget();
|
||||
}
|
||||
|
||||
public static bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
_enabled = value;
|
||||
UpdateTick();
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="waitFinish">if does not get lock, block until last release</param>
|
||||
public static async Task PerformTestAsync(bool waitFinish = false)
|
||||
{
|
||||
if (Lock.CurrentCount == 0)
|
||||
{
|
||||
if (waitFinish)
|
||||
{
|
||||
await Lock.WaitAsync();
|
||||
Lock.Release();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await Lock.WaitAsync();
|
||||
try
|
||||
{
|
||||
var tasks = Global.Settings.Server.Select(async s =>
|
||||
{
|
||||
await PoolLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await s.PingAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
PoolLock.Release();
|
||||
}
|
||||
});
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
Lock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTick(bool performTestAtOnce = false)
|
||||
{
|
||||
UpdateTick(Global.Settings.DetectionTick, performTestAtOnce);
|
||||
}
|
||||
|
||||
/// <param name="interval">interval(seconds), 0 disable, MaxValue <c>int.MaxValue/1000</c></param>
|
||||
/// <param name="performTestAtOnce"></param>
|
||||
private static void UpdateTick(int interval, bool performTestAtOnce = false)
|
||||
{
|
||||
Timer.Stop();
|
||||
|
||||
var enable = Enabled && interval > 0 && Range.InRange(interval);
|
||||
if (enable)
|
||||
{
|
||||
Timer.Interval = interval * 1000;
|
||||
Timer.Start();
|
||||
if (performTestAtOnce)
|
||||
PerformTestAsync().Forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,19 +11,9 @@ namespace Netch.Utils
|
||||
|
||||
public override Server Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader)!;
|
||||
|
||||
try
|
||||
{
|
||||
var type = ServerHelper.GetTypeByTypeName(jsonElement.GetProperty("Type").GetString()!);
|
||||
// TODO replace with .NET 6 Deserialize from DOM
|
||||
return (Server)JsonSerializer.Deserialize(jsonElement.GetRawText(), type)!;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Unsupported Server Type
|
||||
return JsonSerializer.Deserialize<Server>(jsonElement.GetRawText(), new JsonSerializerOptions())!;
|
||||
}
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader);
|
||||
var type = ServerHelper.GetTypeByTypeName(jsonElement.GetProperty("Type").GetString()!);
|
||||
return (Server)JsonSerializer.Deserialize(jsonElement.GetRawText(), type)!;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Server value, JsonSerializerOptions options)
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -23,102 +17,11 @@ namespace Netch.Utils
|
||||
ServerUtilDictionary = serversUtilsTypes.Select(t => (IServerUtil)Activator.CreateInstance(t)!).ToDictionary(util => util.TypeName);
|
||||
}
|
||||
|
||||
#region Delay
|
||||
|
||||
public static class DelayTestHelper
|
||||
{
|
||||
private static readonly Timer Timer;
|
||||
private static readonly object TestAllLock = new();
|
||||
|
||||
private static readonly SemaphoreSlim SemaphoreSlim = new(1, 16);
|
||||
|
||||
public static readonly NumberRange Range = new(0, int.MaxValue / 1000);
|
||||
|
||||
static DelayTestHelper()
|
||||
{
|
||||
Timer = new Timer
|
||||
{
|
||||
Interval = 10000,
|
||||
AutoReset = true
|
||||
};
|
||||
|
||||
Timer.Elapsed += (_, _) => TestAllDelayAsync().Forget();
|
||||
}
|
||||
|
||||
public static bool Enabled
|
||||
{
|
||||
get => Timer.Enabled;
|
||||
set
|
||||
{
|
||||
if (!ValueIsEnabled(Global.Settings.DetectionTick))
|
||||
return;
|
||||
|
||||
Timer.Enabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Interval => (int)(Timer.Interval / 1000);
|
||||
|
||||
private static bool ValueIsEnabled(int value)
|
||||
{
|
||||
return value != 0 && Range.InRange(value);
|
||||
}
|
||||
|
||||
public static async Task TestAllDelayAsync()
|
||||
{
|
||||
if (!Monitor.TryEnter(TestAllLock))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var tasks = Global.Settings.Server.Select(async s =>
|
||||
{
|
||||
await SemaphoreSlim.WaitAsync();
|
||||
try
|
||||
{
|
||||
await s.PingAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
SemaphoreSlim.Release();
|
||||
}
|
||||
});
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(TestAllLock);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateInterval()
|
||||
{
|
||||
Timer.Stop();
|
||||
|
||||
if (!ValueIsEnabled(Global.Settings.DetectionTick))
|
||||
return;
|
||||
|
||||
Timer.Interval = Global.Settings.DetectionTick * 1000;
|
||||
Timer.Start();
|
||||
|
||||
TestAllDelayAsync().Forget();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handler
|
||||
|
||||
public static Dictionary<string, IServerUtil> ServerUtilDictionary { get; set; }
|
||||
public static Dictionary<string, IServerUtil> ServerUtilDictionary { get; }
|
||||
|
||||
public static IServerUtil GetUtilByTypeName(string typeName)
|
||||
{
|
||||
return ServerUtilDictionary[typeName];
|
||||
return ServerUtilDictionary.GetValueOrDefault(typeName) ?? throw new NotSupportedException("Specified server type is not supported.");
|
||||
}
|
||||
|
||||
public static IServerUtil? GetUtilByUriScheme(string scheme)
|
||||
@@ -130,7 +33,5 @@ namespace Netch.Utils
|
||||
{
|
||||
return GetUtilByTypeName(typeName).ServerType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user