2025-03-28 09:49:56 +08:00

1057 lines
49 KiB
C#
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using Transmission.SDK.ThreadPool;
using TransmissionClient.Model;
using BreakpointTransmission.Client;
using Newtonsoft.Json.Linq;
namespace TransmissionClient
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// 注:修改上传/下发的内容:在本页对应配置方法中修改
/// 修改上传/下发需要传输的表及传输类型、传输表时间间隔比例【分钟】、
/// 查询服务区本地数据表SQL语句、初始化传输时间字段、初始化表信息、
/// 定义表传输状态字段、单次最大传输数量在ConfigThread.cs类中修改
/// 修改传输方法在Transmission.SDK中ClientThread.cs类中修改
/// OpenTopThreads、OpenDownThreads、DownLoadDataByServerpaertCode、IsStartDownData方法
/// </summary>
public partial class MainWindow : Window
{
#region Config参数
protected string _OracleConnStr = ConfigurationManager.AppSettings["OracleConnStr"].ToString();
protected string _TimerInterval = ConfigurationManager.AppSettings["Interval"].ToString();
#endregion
#region
/// <summary>
/// 运行状态上报线程
/// </summary>
Thread StateUploadThread { get; set; }
/// <summary>
/// 在线订单线程
/// </summary>
Thread OnlineOrderThread { get; set; }
/// <summary>
/// 在线订单线程
/// </summary>
Thread OldSystemExceptionThread { get; set; }
/// <summary>
/// 压缩文件上传线程
/// </summary>
Thread FileUploadThread { get; set; }
/// <summary>
/// 日结营收数据上传线程
/// </summary>
ClientThread BusinessClientThread = new ClientThread();
/// <summary>
/// 日结营收数据上传配置
/// </summary>
ConfigThread BusinessConfigThread = null;
/// <summary>
/// 日结营收数据上传线程(商业集团)
/// </summary>
ClientThread BusinessClientThread_ZJ = new ClientThread();
/// <summary>
/// 日结营收数据上传配置(商业集团)
/// </summary>
ConfigThread BusinessConfigThread_ZJ = null;
/// <summary>
/// 传输客户端定时器
/// </summary>
DispatcherTimer CilentTimer = new DispatcherTimer();
/// <summary>
/// 在线订单传输定时器
/// </summary>
DispatcherTimer OnlineOrderTimer = new DispatcherTimer();
/// <summary>
/// 公共数据库连接类
/// </summary>
Transmission.SDK.OracleHelper LocalOracle;
/// <summary>
/// 运行日志记录
/// </summary>
DataTable TransResultTable;
/// <summary>
/// 服务区信息缓存表
/// </summary>
DataTable ServerPartTable;
/// <summary>
/// 服务区信息缓存有效期
/// </summary>
DateTime ServerPartCacheTime;
/// <summary>
/// 多链路配置信息
/// </summary>
List<Model.TransLinkConfigModel> TransLinkConfigList { get; set; }
/// <summary>
/// 多链路传输参数库配置
/// </summary>
ConcurrentDictionary<int, MulLinkConfigThread> MulLinkConfigThreadList { get; set; }
/// <summary>
/// 多链路传输线程库配置
/// </summary>
ConcurrentDictionary<int, MulLinkCilentThread> MulLinkCilentThreadList { get; set; }
List<TransferErrorNotifyModel> TransferErrorNotify { get; set; }
bool IsReplaceColumn = false;
string ServerPartCode { get; set; }
#endregion
#region Socket客户端
private SuperSocketClient SocketClient { get; set; }
private string SocketServerpartCode { get; set; }
#endregion
#region ->
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 主窗体加载事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
#region
if (LocalOracle == null || !LocalOracle.ConnTest())
{
LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4],
_OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]);
}
//绑定日结营收数据上传回调事件
BusinessClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定服务区基础数据下载回调事件
BusinessClientThread_ZJ.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//初始化数据传输计时器
CilentTimer.Tick += CilentTimer_Tick;
double timeInterval = 0;
try
{
if (!double.TryParse(_TimerInterval, out timeInterval) || timeInterval < 1 || timeInterval > 10)
{
timeInterval = 5;
}
}
catch
{
timeInterval = 5;
}
timeInterval = timeInterval * 60 * 1000;
CilentTimer.Interval = TimeSpan.FromMilliseconds(timeInterval);
CilentTimer.Start();
//初始化在线订单传输定时器
OnlineOrderTimer.Tick += OnlineOrderTimer_Tick;
OnlineOrderTimer.Interval = TimeSpan.FromSeconds(3);
OnlineOrderTimer.Start();
BtnTimerState.Content = "停止";
Title = "服务区数据传输工具 TCv" + System.Windows.Forms.Application.ProductVersion;
int _FileCount = 0;
string[] _masks = { ".log" };
try
{
//清理过期日志文件
Transmission.SDK.LogHelper.DeleteFiles(
AppDomain.CurrentDomain.BaseDirectory + "\\log",
new string[] { ".log" }, false, false, ref _FileCount);
}
catch { }
#endregion
}
#endregion
#region -> 线
/// <summary>
/// 在线订单传输定时器事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnlineOrderTimer_Tick(object sender, EventArgs e)
{
try
{
string _OnlineService;
try
{
_OnlineService = ConfigurationManager.AppSettings["OnlineService"];
}
catch
{
_OnlineService = "";
}
if (string.IsNullOrWhiteSpace(_OnlineService))
{
TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:参数[OnlineService]未配置。");
OnlineOrderTimer.Stop();
return;
}
if (LocalOracle == null || !LocalOracle.ConnTest())
{
//初始化Oracle数据库连接字符串
LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4],
_OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]);
}
//启动线上订单线程
if (OnlineOrderThread == null || !OnlineOrderThread.IsAlive)
{
OnlineOrderThread = new Thread(() => OnlineOrder(LocalOracle))
{
IsBackground = true
};
OnlineOrderThread.Start();
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "在线订单传输启动失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("在线订单传输启动失败:" + ex.Message);
}
}
#endregion
#region ->
/// <summary>
/// 主窗体按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click(object sender, RoutedEventArgs e)
{
Button _Button = (Button)sender;
switch (_Button.Name)
{
case "BtnTimerState":
if (CilentTimer != null)
{
if (CilentTimer.IsEnabled)
{
CilentTimer.Stop();
_Button.Content = "启动";
TransResultBeginInvoke(DateTime.Now, "数据传输定时器已停止");
}
else
{
CilentTimer.Start();
_Button.Content = "停止";
TransResultBeginInvoke(DateTime.Now, "数据传输定时器已启动");
}
}
else
{
TransResultBeginInvoke(DateTime.Now, "数据传输定时器初始化失败,请重启程序!");
}
break;
case "BtnClosed":
if (CilentTimer != null && CilentTimer.IsEnabled)
{
CilentTimer.Stop();
}
Close();
break;
}
}
#endregion
#region -> 线
/// <summary>
/// 主线程定时器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CilentTimer_Tick(object sender, EventArgs e)
{
try
{
#region
//初始化数据库连接实例
if (LocalOracle == null || !LocalOracle.ConnTest())
{
LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4],
_OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]);
}
#endregion
#region
//检查服务区编码参数,未设置时,从数据库中获取
if (string.IsNullOrWhiteSpace(ServerPartCode))
{
try
{
//从数据库中读取服务区编码信息
var _ServerPartList =
from t in LocalOracle.ExcuteSqlGetDataSet(
"SELECT SERVERPARTCODE FROM HIGHWAY_EXCHANGE.T_SYSCODE").Tables[0].AsEnumerable()
group t by new
{
t1 = t.Field<string>("SERVERPARTCODE")
} into m
select new
{
serverPartCode = m.Key.t1
};
//判断数据库中是否已读取到服务区信息
if (_ServerPartList.ToList().Count() > 0)
{
//多个服务区编码信息用英文逗号( , )拼接在一起,并保存到服务区信息参数属性中
ServerPartCode = string.Join(",", _ServerPartList.Select(p => p.serverPartCode));
}
}
catch { }
}
#endregion
#region
TransResultBeginInvoke(DateTime.Now, "正在预启动上传子线程......");
//初始化门店日结营收数据上传线程配置
if (BusinessConfigThreadConfigure())
{
//启动门店日结营收数据上传线程
if (BusinessClientThread.onState(LocalOracle))
{
TransResultBeginInvoke(DateTime.Now, "日结营收上传线程预启动成功");
}
else
{
TransResultBeginInvoke(DateTime.Now, "日结营收上传线程预启动失败");
}
}
//初始化门店日结营收数据上传线程配置(商业集团)
if (BusinessConfigThreadConfigure_ZJ())
{
//启动门店日结营收数据上传线程
if (BusinessClientThread_ZJ.onState(LocalOracle))
{
TransResultBeginInvoke(DateTime.Now, "日结营收(商业集团)上传线程预启动成功");
}
else
{
TransResultBeginInvoke(DateTime.Now, "日结营收(商业集团)上传线程预启动失败");
}
}
#endregion
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "传输启动失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("传输启动失败:" + ex.Message);
}
}
#endregion
#region -> Socket客户端消息通知事件
/// <summary>
/// Socket客户端消息通知事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SocketClient_NotifyEvent(object sender, Transmission.SDK.Model.Common.NotifyEventArgs e)
{
string DirectoryName = AppDomain.CurrentDomain.BaseDirectory + "/SocketLog";
//记录文本日志
Transmission.SDK.LogHelper.WriteLog(e.NotifyLoggerMessage, "", DirectoryName);
#region /WebSocket/RecordLogToOracleSocket消息通知执行结果到云端
try
{
Transmission.SDK.LogHelper.WriteServiceLog($"是否调用日志上传接口:" + e.NotifyUploadState);
//只有通知上传状态为True的消息才上传到云端
if (e.NotifyUploadState)
{
//文件上传耗时记录
string str_HttpURL = "http://pos.eshangtech.com:7198/webApi_publish/WebSocket/RecordLogToOracle";
string str_PostData = $"ServerpartCode={SocketServerpartCode}&ShopCode=000000&" +
$"MachineCode=0000&LogCentent={e.NotifyLoggerMessage}&TableName={(int)e.NotifyLoggerType}" +
$"&OperateTime={e.NotifyLoggerTime.ToString("yyyyMMddHHmmss")}";
string Result = Transmission.SDK.HttpDataHelper.OnPost($"{str_HttpURL}?{str_PostData}", str_PostData);
Transmission.SDK.LogHelper.WriteServiceLog($"开始上传日志【{str_PostData}】,上传结果:" + Result);
}
}
catch (Exception ex)
{
Transmission.SDK.LogHelper.WriteLog($"{ e.NotifyLoggerType }执行结果上报失败。原因:{ex.Message}", "", DirectoryName);
}
#endregion
//界面显示消息内容
TransResultBeginInvoke(e.NotifyLoggerTime, e.NotifyLoggerMessage);
}
#endregion
#region -> 线
private void BigData_ResultEvent(DateTime triggerTime, string resultMessage)
{
TransResultBeginInvoke(triggerTime, resultMessage);
}
#endregion
#region -> APP运行状态上报
/// <summary>
/// APP运行状态上报
/// </summary>
/// <param name="localOracle">数据库连接类</param>
private void AppStateUpload(Transmission.SDK.OracleHelper localOracle)
{
try
{
if (ServerPartTable == null || ServerPartCacheTime < DateTime.Now)
{
//重置服务区信息缓存表
ServerPartTable = localOracle.ExcuteSqlGetDataSet(
@"SELECT SERVERPART_CODE,PROVINCE_CODE,SERVERPART_NAME
FROM HIGHWAY_EXCHANGE.T_SERVERPART").Tables[0];
if (ServerPartTable.Rows.Count == 0)
{
ServerPartCacheTime = DateTime.Now.AddMinutes(5);
}
else
{
ServerPartCacheTime = DateTime.Now.AddHours(1);
}
}
//定义APP运行状态上报传输地址
string _UploadRuningStateUrl = ConfigurationManager.AppSettings["UploadRuningStateUrl"];
if (string.IsNullOrWhiteSpace(_UploadRuningStateUrl))
{
TransResultBeginInvoke(DateTime.Now, $"APP运行状态上报失败。原因参数[UploadRuningStateUrl]未配置。");
return;
}
foreach (DataRow ServerPartRow in ServerPartTable.Rows)
{
Hashtable hashtable = new Hashtable
{
//省份编码
{ "provinceCode", ServerPartRow["PROVINCE_CODE"].ToString() },
//省份名称
{ "provinceName", "" },
//服务区编码
{ "serverPartCode", ServerPartRow["SERVERPART_CODE"].ToString() },
//服务区名称
{ "serverPartName", ServerPartRow["SERVERPART_NAME"].ToString() },
//运行工具名称
{ "appName", System.Windows.Forms.Application.ProductName },
//运行工具版本号
{ "appVersion", $"TCv{System.Windows.Forms.Application.ProductVersion}" }
};
//上传运行工具状态信息
Transmission.SDK.SoapWSHelper.QuerySoapWebServiceString(
$"{_UploadRuningStateUrl}/Service.asmx", "UploadTransClientState", hashtable);
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"APP运行状态上报失败。原因{ex.Message}");
}
}
#endregion
#region -> 线
/// <summary>
/// 线上订单传输
/// </summary>
/// <param name="localOracle">数据库连接类</param>
private void OnlineOrder(Transmission.SDK.OracleHelper localOracle)
{
TransResultBeginInvoke(DateTime.Now, $"正在启动线上订单数据同步线程......");
try
{
//定义线上订单数据同步地址
string _OnlineService;
try
{
_OnlineService = ConfigurationManager.AppSettings["OnlineService"];
}
catch
{
_OnlineService = "";
}
if (string.IsNullOrWhiteSpace(_OnlineService))
{
TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:参数[OnlineService]未配置。");
return;
}
if (ServerPartTable == null || ServerPartCacheTime < DateTime.Now)
{
//重置服务区信息缓存表
ServerPartTable = localOracle.ExcuteSqlGetDataSet(
@"SELECT SERVERPART_CODE,PROVINCE_CODE,SERVERPART_NAME
FROM HIGHWAY_EXCHANGE.T_SERVERPART").Tables[0];
if (ServerPartTable.Rows.Count == 0)
{
ServerPartCacheTime = DateTime.Now.AddMinutes(5);
}
else
{
ServerPartCacheTime = DateTime.Now.AddHours(1);
}
}
OrderOnline.OnlineTransferResult transferResult;
foreach (DataRow ServerPartRow in ServerPartTable.Rows)
{
//分服务区下载已付款线上订单
TransResultBeginInvoke(DateTime.Now, $"正在下载[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单数据......");
transferResult = OrderOnline.OrderBillDown(localOracle, _OnlineService,
ServerPartRow["SERVERPART_CODE"].ToString(), ServerPartRow["PROVINCE_CODE"].ToString());
TransResultBeginInvoke(DateTime.Now, $"[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单下载完成;" +
$"\n本次订单获取总数{transferResult.TotalCount}条;成功:{transferResult.SuccessCount}条;" +
$"失败:{transferResult.FailCount}条;过滤:{transferResult.FilterCount}条;耗时:{transferResult.TotalSeconds.ToString("F2")}秒。");
//分服务区上传已完成、已制作订单结果
TransResultBeginInvoke(DateTime.Now, $"正在上传[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单接收结果数据......");
transferResult = OrderOnline.OrderBillUpload(localOracle, _OnlineService,
ServerPartRow["SERVERPART_CODE"].ToString(), ServerPartRow["PROVINCE_CODE"].ToString());
TransResultBeginInvoke(DateTime.Now, $"[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单接收结果数据上传完成;" +
$"\n本次订单结果上传总数{transferResult.TotalCount}条;成功:{transferResult.SuccessCount}条;" +
$"失败:{transferResult.FailCount}条;过滤:{transferResult.FilterCount}条;耗时:{transferResult.TotalSeconds.ToString("F2")}秒。");
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:{ex.Message}");
}
}
#endregion
#region ->
/// <summary>
/// 日结营收数据上传线程配置
/// </summary>
private bool BusinessConfigThreadConfigure()
{
//初始化日结营收数据上传地址
string _SalesDataUrl;
try
{
_SalesDataUrl = ConfigurationManager.AppSettings["SalesDataUrl"];
}
catch
{
_SalesDataUrl = "";
}
if (string.IsNullOrWhiteSpace(_SalesDataUrl))
{
TransResultBeginInvoke(DateTime.Now, $"日结营收数据上传线程启动失败。原因:参数[SalesDataUrl]未配置。");
return false;
}
//初始化日结营收数据上传线程配置
if (BusinessConfigThread == null)
{
BusinessConfigThread = new ConfigThread("", IsReplaceColumn);
}
//定义上传表内容
BusinessClientThread.IsUpload(true, new List<string>
{
"T_ENDACCOUNT_NEW", //日结账期表【新】
"T_ENDACCOUNT", //日结账期表【旧】
"T_PERSONSELL_NEW", //收银员交班表【新】
"T_PERSONSELL", //收银员交班表【旧】
});
BusinessClientThread.IsDownload(false);
try
{
//设置配置参数
BusinessClientThread.setConfiguration($"{_SalesDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 1);
//配置线程参数
BusinessClientThread.setConfigThread(BusinessConfigThread);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "日结营收数据上传配置失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("日结营收数据上传配置失败:" + ex.Message);
}
return true;
}
#endregion
#region -> ()
/// <summary>
/// 日结营收数据上传线程配置(商业集团)
/// </summary>
private bool BusinessConfigThreadConfigure_ZJ()
{
//初始化日结营收数据上传地址
string _SalesDataUrl_ZJ;
try
{
_SalesDataUrl_ZJ = ConfigurationManager.AppSettings["SalesDataUrl_ZJ"];
}
catch
{
_SalesDataUrl_ZJ = "";
}
if (string.IsNullOrWhiteSpace(_SalesDataUrl_ZJ))
{
TransResultBeginInvoke(DateTime.Now, $"日结营收数据(商业集团)上传线程启动失败。原因:参数[SalesDataUrl_ZJ]未配置。");
return false;
}
//初始化日结营收数据上传线程配置
if (BusinessConfigThread_ZJ == null)
{
BusinessConfigThread_ZJ = new ConfigThread("", IsReplaceColumn);
}
//定义上传表内容
BusinessClientThread_ZJ.IsUpload(true, new List<string>
{
"T_ENDACCOUNT_ZJ", //日结账期表
"T_PERSONSELL_ZJ", //收银员交班表
});
BusinessClientThread_ZJ.IsDownload(false);
try
{
//设置配置参数
BusinessClientThread_ZJ.setConfiguration($"{_SalesDataUrl_ZJ}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 1);
//配置线程参数
BusinessClientThread_ZJ.setConfigThread(BusinessConfigThread_ZJ);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, "日结营收数据上传配置失败:" + ex.Message);
Transmission.SDK.LogHelper.WriteServiceLog("日结营收数据上传配置失败:" + ex.Message);
}
return true;
}
#endregion
#region ->
/// <summary>
/// 多链路传输配置
/// </summary>
/// <returns></returns>
private bool MulLinkConfigThreadConfigure()
{
//定义多链路传输配置获取服务地址
string str_MulLinkTransConfigUrl;
try
{
//默认读取Config文件中设置的传输链路配置地址;
str_MulLinkTransConfigUrl = ConfigurationManager.AppSettings["MulLinkTransConfigUrl"];
}
catch
{
str_MulLinkTransConfigUrl = "";
}
if (string.IsNullOrWhiteSpace(str_MulLinkTransConfigUrl))
{
//未配置多链路传输配置服务地址时,使用默认地址
str_MulLinkTransConfigUrl = "http://user.eshangtech.com:7088";
//TransResultBeginInvoke(DateTime.Now, $"多链路传输配置失败。原因:参数[MulLinkTransConfigUrl]未配置。");
//return false;
}
if (TransLinkConfigList == null)
{
//当启动程序时,调用服务获取多链路传输配置
TransLinkConfigList = OnTransLinkConfig(ServerPartCode, $"{str_MulLinkTransConfigUrl}/Service.asmx");
}
if (TransLinkConfigList == null || TransLinkConfigList.Count == 0)
{
//当云端未配置当前服务区多链路传输时,不继续初始化线程配置
TransResultBeginInvoke(DateTime.Now, $"多链路传输配置失败。原因:当前服务区云端未配置多链路传输。");
return false;
}
//遍历循环多链路配置列表,初始化每个链路的传输线程配置
foreach (var tlcm_TransLinkConfig in TransLinkConfigList)
{
//初始化链路传输数据类型,每个链路初始化一次
if (!MulLinkConfigThreadList.ContainsKey(tlcm_TransLinkConfig.TransLinkID))
{
MulLinkConfigThread mulLinkConfig = new MulLinkConfigThread(tlcm_TransLinkConfig.TableConfig, ServerPartCode);
MulLinkConfigThreadList.AddOrUpdate(tlcm_TransLinkConfig.TransLinkID, mulLinkConfig, (TransLinkID, MulLinkConfig) => mulLinkConfig);
}
//检查当前传输链路是否实例化传输线程配置
if (!MulLinkCilentThreadList.ContainsKey(tlcm_TransLinkConfig.TransLinkID))
{
//添加当前线程配置至线程列表
MulLinkCilentThread mulLinkCilent = new MulLinkCilentThread();
//绑定多链路线程上传回调事件
mulLinkCilent.UploadStringEvent += new MulLinkCilentThread.OutputResultsUploadArg(ClientThread_UploadStringEvent);
//绑定多链路线程下载回调事件
mulLinkCilent.DownloadStringEvent += new MulLinkCilentThread.OutputResultsDownArg(ClientThread_DownloadStringEvent);
MulLinkCilentThreadList.AddOrUpdate(tlcm_TransLinkConfig.TransLinkID, mulLinkCilent, (TransLinkID, MulLinkCilent) => mulLinkCilent);
}
//根据云端链路配置,设置需要启动传输的数据类型
List<string> _TransTableList = new List<string>();
foreach (var tc_TableConfig in tlcm_TransLinkConfig.TableConfig)
{
string[] str_TableName = tc_TableConfig.TableName.Split('.');
if (str_TableName.Length > 1)
{
_TransTableList.Add(str_TableName[1]);
//如多链路传输的数据上次给类型为状态反馈【T_STATEFEEDBACK】时需加上区服数据版本上传表类型【T_SERVERPARTFEEDBACK】
if (str_TableName[1] == "T_STATEFEEDBACK")
{
_TransTableList.Add("T_SERVERPARTFEEDBACK");
}
}
else
{
_TransTableList.Add(str_TableName[0]);
//如多链路传输的数据上次给类型为状态反馈【T_STATEFEEDBACK】时需加上区服数据版本上传表类型【T_SERVERPARTFEEDBACK】
if (str_TableName[0] == "T_STATEFEEDBACK")
{
_TransTableList.Add("T_SERVERPARTFEEDBACK");
}
}
}
try
{
//设置上传启动的表
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].IsUpload(true, _TransTableList);
//设置下发启动的表
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].IsDownload(true, _TransTableList);
//设置数据传输的链路地址
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].setConfiguration(tlcm_TransLinkConfig.TransLinkURL, "", ServerPartCode, "", "", "", "", 20, 1);
//设置数据传输线程参数
MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].setConfigThread(MulLinkConfigThreadList[tlcm_TransLinkConfig.TransLinkID]);
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"链路[{tlcm_TransLinkConfig.TransLinkURL}]传输配置失败:" + ex.Message);
}
}
return true;
}
#endregion
#region ->
/// <summary>
/// 获取服务区多链路传输配置信息
/// </summary>
/// <param name="serverpartCode">服务区编码,多个使用英文逗号【,】隔开888888,888889</param>
/// <param name="serviceUrl">多链路传输配置获取服务地址格式http://127.0.0.1:7080/service.asmx </param>
/// <returns></returns>
private List<TransLinkConfigModel> OnTransLinkConfig(string serverpartCode, string serviceUrl)
{
List<TransLinkConfigModel> tlcm_TransLinkConfigList = new List<TransLinkConfigModel>();
try
{
//调用云端多链路配置服务接口,获取当前服务区多链路配置信息
string str_MulLinkTransConfig = Transmission.SDK.SoapWSHelper.QuerySoapWebServiceString(
serviceUrl, "GetMulLinkTransConfig", new Hashtable() { { "serverpartCodes", serverpartCode } });
if (string.IsNullOrWhiteSpace(str_MulLinkTransConfig))
{
//云端接口无返回值时,返回空白配置信息
return tlcm_TransLinkConfigList;
}
//反序列化返回值为JSon对象
JObject jObject_MulLinkTransConfig = JObject.Parse(str_MulLinkTransConfig);
if (jObject_MulLinkTransConfig.Property("IsSuccess") == null ||
jObject_MulLinkTransConfig.Property("IsSuccess").Value.ToString() != "1")
{
//当接口返回值IsSuccess不等于1时代表接口不成功返回空白配置信息
return tlcm_TransLinkConfigList;
}
//解析多链路配置为List实体
List<Model.MulLinkConfigModel> mlcm_MulLinkConfigModelList = jObject_MulLinkTransConfig.Property("Obj").Value.ToObject<List<Model.MulLinkConfigModel>>();
//var tmp_MulLinkConfigList = mlcm_MulLinkConfigModelList.Select(p => new { p.MulLinkConfig_ID, p.InterfaceAddress, p.ServerPartCode }).Distinct().ToList();
//多链路传输地址去重
var tmp_MulLinkConfigList = mlcm_MulLinkConfigModelList.Select(p => new { p.MulLinkConfig_ID, p.InterfaceAddress }).Distinct().ToList();
//遍历循环获取到的多链路信息,转化为本地多链路配置实体属性
foreach (var _MulLinkConfig in tmp_MulLinkConfigList)
{
TransLinkConfigModel temp_TransLinkConfig = new TransLinkConfigModel();
//设置链路唯一标识,用于多链路线程配置识别
temp_TransLinkConfig.TransLinkID = (int)_MulLinkConfig.MulLinkConfig_ID;
//设置链路传输真实服务地址
temp_TransLinkConfig.TransLinkURL = $"{_MulLinkConfig.InterfaceAddress}/Service.asmx";
//temp_TransLinkConfig.ServerPartCode = _MulLinkConfig.ServerPartCode;
//设置链路传输服务区编码
temp_TransLinkConfig.ServerPartCode = serverpartCode;
//设置链路传输启动的表数据类型
temp_TransLinkConfig.TableConfig = new List<TransTableConfigModel>();
List<Model.MulLinkConfigModel> temp_TransTable = mlcm_MulLinkConfigModelList.FindAll(p =>
{
return p.MulLinkConfig_ID == _MulLinkConfig.MulLinkConfig_ID;//&& p.ServerPartCode == _MulLinkConfig.ServerPartCode;
});
//循环添加需要启动传输的数据表类型至配置列表
for (int i = 0; i < temp_TransTable.Count; i++)
{
TransTableConfigModel temp_TransTableConfig = new TransTableConfigModel();
if (temp_TransTable[i].TransFrequence != null)
{
temp_TransTableConfig.TransFrequence = (int)temp_TransTable[i].TransFrequence.Value;
}
temp_TransTableConfig.TableName = temp_TransTable[i].TableName;
temp_TransTableConfig.HistoryCallbackDate = temp_TransTable[i].HistoryCallBackDate;
temp_TransTableConfig.HistoryCallbackDays = (int)temp_TransTable[i].HistoryCallBackDays;
temp_TransTableConfig.StartTime = (int)temp_TransTable[i].StartTime;
temp_TransTableConfig.EndTime = (int)temp_TransTable[i].EndTime;
temp_TransLinkConfig.TableConfig.Add(temp_TransTableConfig);
}
tlcm_TransLinkConfigList.Add(temp_TransLinkConfig);
}
}
catch (Exception ex)
{
TransResultBeginInvoke(DateTime.Now, $"多链路传输配置获取异常。原因:{ex.Message}");
}
return tlcm_TransLinkConfigList;
}
#endregion
#region ->
/// <summary>
/// 上传回调事件
/// </summary>
/// <param name="uploadResultInfo"></param>
/// <param name="resultString"></param>
private void ClientThread_UploadStringEvent(UploadResultInfo uploadResultInfo, string resultString)
{
if (uploadResultInfo.StartToEnd)
{
TransResultBeginInvoke(DateTime.Now, resultString);
}
else
{
//于窗体中显示上传结果
TransResultBeginInvoke(DateTime.Now, string.Format("上传完成:[{0}]\n     总数{1};成功:{2};过滤:{3};失败:{5};耗时:{4}{6}",
uploadResultInfo.TableName, uploadResultInfo.TotalNumber, uploadResultInfo.SuccessNumber,
uploadResultInfo.FilterNumber, uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒",
uploadResultInfo.TotalNumber - uploadResultInfo.SuccessNumber - uploadResultInfo.FilterNumber,
(string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError) ? "" : ("\n     接口错误" + uploadResultInfo.InterfaceError)) +
(string.IsNullOrWhiteSpace(uploadResultInfo.Error) ? "" : ("\n     本地错误" + uploadResultInfo.Error))));
//若上传出现异常,则记录日志文本文件
if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError) || !string.IsNullOrWhiteSpace(uploadResultInfo.Error))
{
//接口报错,记录异常变量,延迟重试传输
if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError))
{
CheckTransferErrorNotify(uploadResultInfo.TableName, uploadResultInfo.ServiceURL);
}
//记录接口错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError))
{
Transmission.SDK.LogHelper.WriteServiceLog("接口错误:" + uploadResultInfo.InterfaceError +
$"\n{uploadResultInfo.TableDesc}数据上传错误:[{uploadResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}]" +
$"耗时:{uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
//记录本地错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(uploadResultInfo.Error))
{
Transmission.SDK.LogHelper.WriteServiceLog("本地错误:" + uploadResultInfo.Error +
$"\n{uploadResultInfo.TableDesc}数据上传错误:[{uploadResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}]" +
$"耗时:{uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
}
else
{
if (TransferErrorNotify != null)
{
TransferErrorNotify.RemoveAll(p => p.ServiceURL == uploadResultInfo.ServiceURL);
}
}
}
}
#endregion
#region ->
/// <summary>
/// 下载回调事件
/// </summary>
/// <param name="downResultInfo"></param>
/// <param name="resultString"></param>
private void ClientThread_DownloadStringEvent(DownResultInfo downResultInfo, string resultString)
{
if (downResultInfo.StartToEnd)
{
TransResultBeginInvoke(DateTime.Now, resultString);
}
else
{
//于窗体中显示下载结果
TransResultBeginInvoke(DateTime.Now, string.Format("下载完成:[{0}]\n     总数{1};新增:{2};更新:{3};过滤:{4};耗时:{5}{6}",
downResultInfo.TableName, downResultInfo.TotalNumber, downResultInfo.AddNumber, downResultInfo.UpNumber,
downResultInfo.FilterNumber, downResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒",
(string.IsNullOrWhiteSpace(downResultInfo.InterfaceError) ? "" : ("\n     接口错误" + downResultInfo.InterfaceError)) +
(string.IsNullOrWhiteSpace(downResultInfo.Error) ? "" : ("\n     本地错误" + downResultInfo.Error))));
//若下载出现异常,则记录日志文本文件
if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError) || !string.IsNullOrWhiteSpace(downResultInfo.Error))
{
//接口报错,记录异常变量,延迟重试传输
if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError))
{
CheckTransferErrorNotify(downResultInfo.TableName, downResultInfo.ServiceURL);
}
//记录接口错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError))
{
Transmission.SDK.LogHelper.WriteServiceLog("接口错误:" + downResultInfo.InterfaceError +
$"\n{downResultInfo.TableDesc}数据获取错误:[{downResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{downResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
//记录本地错误信息到文本日志中,供后续排查
if (!string.IsNullOrWhiteSpace(downResultInfo.Error))
{
Transmission.SDK.LogHelper.WriteServiceLog("本地错误:" + downResultInfo.Error +
$"\n{downResultInfo.TableDesc}数据获取错误:[{downResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{downResultInfo.Elapsed.TotalSeconds.ToString("F2") + ""}");
}
}
else
{
if (TransferErrorNotify != null)
{
TransferErrorNotify.RemoveAll(p => p.ServiceURL == downResultInfo.ServiceURL);
}
}
}
}
/// <summary>
/// 接口异常记录缓存
/// </summary>
/// <param name="tableName">传输表名</param>
/// <param name="serviceURL">传输接口地址</param>
private void CheckTransferErrorNotify(string tableName, string serviceURL)
{
//初始化缓存变量
if (TransferErrorNotify == null)
{
TransferErrorNotify = new List<TransferErrorNotifyModel>();
}
//读取缓存的对应数据表传输异常变量
TransferErrorNotifyModel tenm_TransferErrorNotify = TransferErrorNotify.Find(p => p.ServiceURL == serviceURL);
//
if (tenm_TransferErrorNotify == null)
{
tenm_TransferErrorNotify = new TransferErrorNotifyModel();
//tenm_TransferErrorNotify.TableName = tableName;
tenm_TransferErrorNotify.ServiceURL = serviceURL;
TransferErrorNotify.Add(tenm_TransferErrorNotify);
}
//记录接口报错重试次数
if (tenm_TransferErrorNotify.ErrorCount < 10)
{
tenm_TransferErrorNotify.ErrorCount += 1;
}
tenm_TransferErrorNotify.LastErrorTime = DateTime.Now;
if (tenm_TransferErrorNotify.ErrorCount >= 3)
{
tenm_TransferErrorNotify.RestartTime = DateTime.Now.AddMinutes(5);
}
}
#endregion
#region ->
private delegate void DelegateTransResult(DateTime triggerTime, string resultMessage);
private void TransResultBeginInvoke(DateTime triggerTime, string resultMessage)
{
Dispatcher.BeginInvoke(new DelegateTransResult(TransResult), new object[] { triggerTime, resultMessage });
}
/// <summary>
/// 运行日志呈现
/// </summary>
/// <param name="triggerTime">日志时间</param>
/// <param name="resultMessage">日志内容</param>
private void TransResult(DateTime triggerTime, string resultMessage)
{
if (TransResultTable == null)
{
TransResultTable = ResultTable();
}
foreach (DataRow _RowTemp in TransResultTable.Select(string.Format("TransDate < '{0}'", DateTime.Now.AddHours(-1))))
{
TransResultTable.Rows.Remove(_RowTemp);
}
TransResultTable.AcceptChanges();
DataRow _DataRow = TransResultTable.NewRow();
_DataRow["TransDate"] = triggerTime;
_DataRow["TransResult"] = resultMessage;
TransResultTable.Rows.InsertAt(_DataRow, 0);
DataTransResult.AutoGenerateColumns = false;
DataTransResult.SelectionMode = DataGridSelectionMode.Single;
DataTransResult.ItemsSource = TransResultTable.DefaultView;
}
/// <summary>
/// 运行日志记录表结构
/// </summary>
/// <returns></returns>
private DataTable ResultTable()
{
DataTable _DataTable = new DataTable();
_DataTable.Columns.Add("TransDate", typeof(DateTime));
_DataTable.Columns.Add("TransResult", typeof(string));
return _DataTable;
}
#endregion
#region ->
/// <summary>
/// 方法 -> 比较两集合值
/// </summary>
/// <param name="listOne">集合</param>
/// <param name="listTwo">集合</param>
/// <param name="isCase">是否区分大小写</param>
private bool IsListCompare(List<string> listOne, List<string> listTwo, bool isCase = false)
{
if (listOne == null && listTwo == null)
{
return true;
}
if (listOne != null && listTwo != null)
{
if (listOne.Count == listTwo.Count)
{
foreach (string tempOne in listOne)
{
foreach (string tempTwo in listTwo)
{
if (isCase)
{
if (!tempOne.Equals(tempTwo))
{
return false;
}
}
else
{
if (!tempOne.ToUpper().Equals(tempTwo.ToUpper()))
{
return false;
}
}
}
}
return true;
}
}
return false;
}
#endregion
}
}