Compare commits
14 Commits
39fbf5570c
...
3e617309f7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e617309f7 | ||
|
|
5b8e9d1a19 | ||
|
|
49939dc14c | ||
|
|
b9e6db147c | ||
|
|
718cec11a5 | ||
|
|
959b4232aa | ||
|
|
40dce42fd7 | ||
|
|
65a3117d10 | ||
|
|
fc09f64873 | ||
|
|
bb0706e7b7 | ||
|
|
370ab2ea7c | ||
|
|
6042411a01 | ||
|
|
32409ebe2b | ||
|
|
6d31ffc78d |
@@ -144,15 +144,165 @@ namespace WinISP.BaseClass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly object _graphicsCardLock = new object();
|
||||||
|
private volatile bool _isDisposing = false;
|
||||||
|
|
||||||
private void FreeGraphicsCardCtrl()
|
private void FreeGraphicsCardCtrl()
|
||||||
{
|
{
|
||||||
// Free the GCHandle.
|
lock (_graphicsCardLock)
|
||||||
frmISP.WriteLog("Free the GCHandle.", "debug");
|
{
|
||||||
if (gch.IsAllocated)
|
// 防止重复释放
|
||||||
gch.Free();
|
if (_isDisposing)
|
||||||
DisposeGraphicCardCtrl();
|
{
|
||||||
pGraphicCardCtrl = IntPtr.Zero;
|
frmISP.WriteLog("Graphics card control is already being disposed, skipping.", "warn");
|
||||||
_IsInit = false;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_IsInit)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog("Graphics card control is not initialized, nothing to free.", "debug");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isDisposing = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 第一步:释放 GCHandle
|
||||||
|
FreeGCHandle();
|
||||||
|
|
||||||
|
// 第二步:释放图形卡控制资源
|
||||||
|
DisposeGraphicsCardControl();
|
||||||
|
|
||||||
|
// 第三步:清空指针
|
||||||
|
pGraphicCardCtrl = IntPtr.Zero;
|
||||||
|
|
||||||
|
// 第四步:更新状态
|
||||||
|
_IsInit = false;
|
||||||
|
|
||||||
|
frmISP.WriteLog("Graphics card control freed successfully.", "info");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"Error freeing graphics card control: {ex.GetType().Name} - {ex.Message}", "error");
|
||||||
|
// 即使出错也要尝试清理状态
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pGraphicCardCtrl = IntPtr.Zero;
|
||||||
|
_IsInit = false;
|
||||||
|
}
|
||||||
|
catch (Exception cleanupEx)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"Error during cleanup after exception: {cleanupEx.Message}", "error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isDisposing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 安全释放 GCHandle
|
||||||
|
/// </summary>
|
||||||
|
private void FreeGCHandle()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (gch.IsAllocated)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog("Freeing GCHandle...", "debug");
|
||||||
|
gch.Free();
|
||||||
|
frmISP.WriteLog("GCHandle freed successfully.", "debug");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frmISP.WriteLog("GCHandle is not allocated, skipping free operation.", "debug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"InvalidOperationException when freeing GCHandle: {ex.Message}", "warn");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"Unexpected exception when freeing GCHandle: {ex.GetType().Name} - {ex.Message}", "error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 安全释放图形卡控制资源
|
||||||
|
/// </summary>
|
||||||
|
private void DisposeGraphicsCardControl()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (pGraphicCardCtrl != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog("Disposing graphics card control...", "debug");
|
||||||
|
DisposeGraphicCardCtrl();
|
||||||
|
frmISP.WriteLog("Graphics card control disposed successfully.", "debug");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frmISP.WriteLog("Graphics card control pointer is null, skipping dispose.", "debug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (AccessViolationException ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"AccessViolationException when disposing graphics card control: {ex.Message}", "error");
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"ObjectDisposedException when disposing graphics card control: {ex.Message}", "warn");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"Unexpected exception when disposing graphics card control: {ex.GetType().Name} - {ex.Message}", "error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证图形卡控制是否已正确释放
|
||||||
|
/// </summary>
|
||||||
|
public bool IsGraphicsCardControlFreed()
|
||||||
|
{
|
||||||
|
lock (_graphicsCardLock)
|
||||||
|
{
|
||||||
|
return !_IsInit && pGraphicCardCtrl == IntPtr.Zero && !gch.IsAllocated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 强制清理(用于异常恢复)
|
||||||
|
/// </summary>
|
||||||
|
public void ForceCleanupGraphicsCardCtrl()
|
||||||
|
{
|
||||||
|
lock (_graphicsCardLock)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
frmISP.WriteLog("Performing force cleanup of graphics card control...", "warn");
|
||||||
|
|
||||||
|
// 强制释放 GCHandle
|
||||||
|
if (gch.IsAllocated)
|
||||||
|
{
|
||||||
|
try { gch.Free(); }
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 强制清空指针
|
||||||
|
pGraphicCardCtrl = IntPtr.Zero;
|
||||||
|
_IsInit = false;
|
||||||
|
|
||||||
|
frmISP.WriteLog("Force cleanup completed.", "info");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
frmISP.WriteLog($"Error during force cleanup: {ex.Message}", "error");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphicCardI2CCtrl()
|
public GraphicCardI2CCtrl()
|
||||||
@@ -248,33 +398,30 @@ namespace WinISP.BaseClass
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteData(byte[] data)
|
public bool WriteData(byte[] data)
|
||||||
{
|
{
|
||||||
Byte slvAddr = data[0];
|
Byte slvAddr = data[0];
|
||||||
Byte[] wrBuf = new Byte[data.Length - 1];
|
Byte[] wrBuf = new Byte[data.Length - 1];
|
||||||
Array.Copy(data, 1, wrBuf, 0, wrBuf.Length);
|
Array.Copy(data, 1, wrBuf, 0, wrBuf.Length);
|
||||||
const Byte maxWrLen = 16;
|
|
||||||
int idx = 0;
|
bool ret = DDCWrite(pGraphicCardCtrl, slvAddr, (uint)wrBuf.Length, wrBuf);
|
||||||
unsafe
|
frmISP.WriteLog($"[DDCWrite] card={GraphicCardType} slv=0x{slvAddr:X2} len={wrBuf.Length} ret={ret}", ret ? "debug" : "error");
|
||||||
{
|
return ret;
|
||||||
fixed (Byte* pArr = wrBuf)
|
|
||||||
{
|
|
||||||
return DDCWrite(pGraphicCardCtrl, slvAddr, (uint)(wrBuf.Length), wrBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadData(byte[] data, byte[] wrCmds = null)
|
public bool ReadData(byte[] data, byte[] wrCmds = null)
|
||||||
{
|
{
|
||||||
uint revlen = (uint)data.Length;
|
if (wrCmds == null || wrCmds.Length == 0)
|
||||||
unsafe
|
|
||||||
{
|
{
|
||||||
fixed (Byte* pArr = data)
|
frmISP.WriteLog($"[DDCRead] card={GraphicCardType} wrCmds is NULL/empty!", "error");
|
||||||
{
|
return false;
|
||||||
return DDCRead(pGraphicCardCtrl, wrCmds[0], revlen, data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
uint revlen = (uint)data.Length;
|
||||||
|
bool ret = DDCRead(pGraphicCardCtrl, wrCmds[0], revlen, data);
|
||||||
|
frmISP.WriteLog($"[DDCRead] card={GraphicCardType} slv=0x{wrCmds[0]:X2} rdLen={revlen} ret={ret} " +
|
||||||
|
$"first4={(data.Length >= 4 ? BitConverter.ToString(data, 0, 4) : "n/a")}", ret ? "debug" : "error");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Init()
|
public bool Init()
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using WinISP;
|
||||||
|
|
||||||
namespace MTK
|
namespace MTK
|
||||||
{
|
{
|
||||||
@@ -72,6 +74,12 @@ namespace MTK
|
|||||||
strData = "";
|
strData = "";
|
||||||
if (_i2cCtrl.ReadData(recvBuf, wrCmds) == true)
|
if (_i2cCtrl.ReadData(recvBuf, wrCmds) == true)
|
||||||
{
|
{
|
||||||
|
frmISP.WriteLog(
|
||||||
|
$"[DDC_Read RAW] cmd=0x{data[1]:X2} recvLen={recvLen} " +
|
||||||
|
$"raw=[{string.Join(" ", recvBuf.Select(b => b.ToString("X2")))}]",
|
||||||
|
"debug");
|
||||||
|
|
||||||
|
// ────────
|
||||||
for (int i = 0; i < recvBuf.Length; ++i)
|
for (int i = 0; i < recvBuf.Length; ++i)
|
||||||
strData += recvBuf[i].ToString("X2") + " ";
|
strData += recvBuf[i].ToString("X2") + " ";
|
||||||
|
|
||||||
@@ -102,6 +110,29 @@ namespace MTK
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从 DDC 0x6F 继续读取数据(不重新发送命令)。
|
||||||
|
/// 用于 N卡 DP AUX 通道 16 字节限制导致截断时的分段续读。
|
||||||
|
/// 在 DDC_Read 成功返回后立即调用,尝试读取响应缓冲区中尚未消费的剩余字节。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="recvLen">要读取的字节数</param>
|
||||||
|
/// <returns>读取到的字节数组,失败返回 null</returns>
|
||||||
|
public static Byte[] DDC_ReadContinue(int recvLen)
|
||||||
|
{
|
||||||
|
const Byte dest = 0x6F;
|
||||||
|
Byte[] wrCmds = { dest };
|
||||||
|
Byte[] recvBuf = new Byte[recvLen];
|
||||||
|
if (_i2cCtrl.ReadData(recvBuf, wrCmds))
|
||||||
|
{
|
||||||
|
frmISP.WriteLog(
|
||||||
|
$"[DDC_ReadContinue] rdLen={recvLen} raw=[{string.Join(" ", recvBuf.Select(b => b.ToString("X2")))}]",
|
||||||
|
"debug");
|
||||||
|
return recvBuf;
|
||||||
|
}
|
||||||
|
frmISP.WriteLog($"[DDC_ReadContinue] rdLen={recvLen} read failed", "debug");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static Byte CalCheckSum(Byte[] data, int startIdx = 0)
|
private static Byte CalCheckSum(Byte[] data, int startIdx = 0)
|
||||||
{
|
{
|
||||||
Byte chkSum = 0;
|
Byte chkSum = 0;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1859,21 +1859,38 @@ namespace WinISP
|
|||||||
private static string resultFolder = System.IO.Directory.GetCurrentDirectory() + "\\";
|
private static string resultFolder = System.IO.Directory.GetCurrentDirectory() + "\\";
|
||||||
private static System.IO.StreamWriter _logWriter = null;
|
private static System.IO.StreamWriter _logWriter = null;
|
||||||
private static string _logPath = null;
|
private static string _logPath = null;
|
||||||
|
private static readonly object _logLock = new object();
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
public static void WriteLog(string str, string fileName)
|
public static void WriteLog(string str, string level)
|
||||||
{
|
{
|
||||||
if (!System.IO.Directory.Exists(resultFolder))
|
try
|
||||||
System.IO.Directory.CreateDirectory(resultFolder);
|
|
||||||
|
|
||||||
string path = resultFolder + (fileName == "" ? "" : fileName + "_") + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
|
|
||||||
if (_logWriter == null || _logPath != path)
|
|
||||||
{
|
{
|
||||||
if (_logWriter != null) { _logWriter.Flush(); _logWriter.Close(); }
|
if (!System.IO.Directory.Exists(resultFolder))
|
||||||
_logPath = path;
|
System.IO.Directory.CreateDirectory(resultFolder);
|
||||||
_logWriter = new System.IO.StreamWriter(path, append: true);
|
|
||||||
|
string path = resultFolder + (level == "" ? "" : level + "_") + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
|
||||||
|
|
||||||
|
lock (_logLock) // >>> 新增:同进程内串行化,避免自家多线程争用
|
||||||
|
{
|
||||||
|
if (_logWriter == null || _logPath != path)
|
||||||
|
{
|
||||||
|
if (_logWriter != null)
|
||||||
|
{
|
||||||
|
try { _logWriter.Flush(); _logWriter.Close(); } catch { }
|
||||||
|
}
|
||||||
|
_logPath = path;
|
||||||
|
var stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
|
||||||
|
_logWriter = new System.IO.StreamWriter(stream);
|
||||||
|
}
|
||||||
|
_logWriter.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str);
|
||||||
|
_logWriter.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception) // >>> 改动:IOException → Exception,吞掉一切日志异常
|
||||||
|
{
|
||||||
|
// 日志写入失败绝不能影响主流程。可选:降级写到 Debug 输出
|
||||||
|
try { System.Diagnostics.Debug.WriteLine("[LOG-FALLBACK] " + str); } catch { }
|
||||||
}
|
}
|
||||||
_logWriter.WriteLine(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.fff: ") + str);
|
|
||||||
_logWriter.Flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cboConnectedMonitor_SelectedIndexChanged(object sender, EventArgs e)
|
private void cboConnectedMonitor_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user