using HH.WCS.HangYang.api;
|
using HH.WCS.HangYang.core;
|
using HH.WCS.HangYang.device;
|
using HH.WCS.HangYang.process;
|
using HH.WCS.HangYang.util;
|
using HH.WCS.HangYang.wms;
|
using Microsoft.Owin.Hosting;
|
using NLog;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Linq;
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using Topshelf;
|
using Monitor = HH.WCS.HangYang.core.Monitor;
|
|
namespace HH.WCS.HangYang
|
{
|
internal class Program
|
{
|
static void Main(string[] args)
|
{
|
|
|
Settings.Init();
|
//1.0 开启api
|
Startup();
|
//2.0 开启tcp
|
StartTcp();
|
//3.0 开启线程
|
var rc = HostFactory.Run(x =>
|
{
|
using (var worker = new WorkThread())
|
{
|
worker.Start();
|
|
// 主线程等待退出信号
|
Console.CancelKeyPress += (s, e) => worker.Stop();
|
Thread.Sleep(Timeout.Infinite);
|
}
|
x.RunAsLocalSystem();
|
|
x.SetDescription("hh123");
|
x.SetDisplayName("hh123.wms");
|
x.SetServiceName("hh123.wms");
|
});
|
|
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());
|
Environment.ExitCode = exitCode;
|
}
|
|
private static void Startup()
|
{
|
Console.WriteLine("Startup ApiController");
|
Task.Run(() =>
|
{
|
//var url = "http://192.168.1.87:8901";//{SettingHelper.port}
|
var url = $"http://+:{Settings.port}";//
|
Console.WriteLine(url);
|
using (WebApp.Start<Startup>(url))
|
{
|
Console.WriteLine("Running on {0}", url);
|
Console.ReadLine();
|
}
|
});
|
}
|
private static void StartTcp()
|
{
|
//new TcpServer("192.168.1.87");
|
var host = Dns.GetHostEntry(Dns.GetHostName());
|
foreach (var ip in host.AddressList)
|
{
|
if (ip.AddressFamily == AddressFamily.InterNetwork)
|
{
|
Console.WriteLine($"ip= {ip.ToString()}");
|
new TcpServer(ip.ToString());
|
}
|
}
|
}
|
|
|
public class WorkThread : IDisposable
|
{
|
private readonly List<Task> _tasks = new List<Task>();
|
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
private bool _disposed;
|
|
private readonly Dictionary<string, Action> _taskRegistry = new Dictionary<string, Action>
|
{
|
{"循环作业创建任务", WCSCore.ExecuteJob},
|
{"循环入库暂存区生成入库任务", WCSCore.ProcessZoneInventoryCycle},
|
{"根据配盘单生成出库任务", WCSCore.GenerateFromPicking},
|
};
|
|
|
private readonly List<(string Name, Action Action, Task Task)> _taskInfoList = new List<(string, Action, Task)>();
|
|
public void Start()
|
{
|
|
// 创建所有任务
|
foreach (var task in _taskRegistry)
|
{
|
var managedTask = CreateManagedTask(task.Value, task.Key, _cts.Token);
|
_taskInfoList.Add((task.Key, task.Value, managedTask));
|
_tasks.Add(managedTask);
|
}
|
|
// 启动健康监控
|
_tasks.Add(StartHealthMonitor());
|
|
LogHelper.Info($"工作线程已启动,共 {_tasks.Count} 个任务");
|
|
}
|
public void Stop()
|
{
|
if (_cts.IsCancellationRequested) return;
|
|
LogHelper.Info("正在停止工作线程...");
|
_cts.Cancel();
|
|
Task.WhenAll(_tasks)
|
.ContinueWith(t =>
|
{
|
_tasks.Clear();
|
LogHelper.Info("所有工作线程已停止");
|
});
|
}
|
private Task CreateManagedTask(Action action, string taskName, CancellationToken ct)
|
{
|
int retryCount = 0;
|
|
return Task.Run(async () =>
|
{
|
LogHelper.Info($"任务 [{taskName}] 启动");
|
|
while (!ct.IsCancellationRequested)
|
{
|
try
|
{
|
var stopwatch = Stopwatch.StartNew();
|
action();
|
stopwatch.Stop();
|
|
if (stopwatch.ElapsedMilliseconds > 10000)
|
{
|
LogHelper.Info($"任务 [{taskName}] 执行时间过长: {stopwatch.ElapsedMilliseconds}ms");
|
}
|
}
|
catch (OperationCanceledException)
|
{
|
LogHelper.Info($"任务 [{taskName}] 已取消");
|
break;
|
}
|
catch (Exception ex)
|
{
|
LogHelper.Error($"任务 [{taskName}] 执行失败: {ex.Message}", ex);
|
var delay = Math.Min(30000, 1000 * (int)Math.Pow(2, retryCount));
|
await Task.Delay(delay, ct);
|
retryCount++;
|
}
|
|
await Task.Delay(3000, ct);
|
}
|
|
LogHelper.Info($"任务 [{taskName}] 已退出");
|
}, ct);
|
}
|
public void Dispose()
|
{
|
if (_disposed) return;
|
|
Stop();
|
_cts.Dispose();
|
_disposed = true;
|
GC.SuppressFinalize(this);
|
}
|
|
private Task StartHealthMonitor()
|
{
|
return Task.Run(async () =>
|
{
|
while (!_cts.IsCancellationRequested)
|
{
|
var faultedTasks = _taskInfoList.Where(x => x.Task.IsFaulted).ToList();
|
foreach (var (name, action, task) in faultedTasks)
|
{
|
LogHelper.Info($"检测到失败任务: {name}");
|
|
// 移除旧任务
|
_taskInfoList.Remove((name, action, task));
|
_tasks.Remove(task);
|
|
// 创建新任务
|
var newTask = CreateManagedTask(action, name, _cts.Token);
|
_taskInfoList.Add((name, action, newTask));
|
_tasks.Add(newTask);
|
}
|
|
await Task.Delay(10000, _cts.Token);
|
}
|
}, _cts.Token);
|
}
|
|
}
|
}
|
}
|