我最近正在处理一个多线程项目,遇到一个问题。
只要传感器在流式传输,就会每220毫秒调用一次SafeCreateProcessThread();
。
public void StreamingDisplayMonitor()
{
var dtStartTemp = DateTime.Now;
while (IsStreaming)
{
if ((DateTime.Now - dtStartTemp).TotalMilliseconds >= 220)
{
SafeCreateProcessThread();
dtStartTemp = DateTime.Now;
}
if (SystemManager.bleTask.DicConnection.Count == 0) IsStreaming = false;
}
}
这是启动线程的方法:
private void SafeCreateProcessThread()
{
var th = new Thread(() => ProcessStreamingData());
th.IsBackground = true;
th.Start();
th.Join(230);
if (th.IsAlive)
{
// timeout
// terminate the thread and release the lock
}
}
和ProcessStreamingData()
如下
private void ProcessStreamingData()
{
var sensorCount = ConnectedSensors.Length;
for (int i = 0; i < sensorCount; i++)
{
lock (lockObject1)
{
var sensor = ConnectedSensors[i];
if (sensor.lst_streaming_data.Count > 0)
{
var streamingPacket = sensor.lst_streaming_data.Last();
var calibrateMag = sensor.attitudeHelper.CalibrateStreamingPacket(streamingPacket, sensor);
sensor.attitudeHelper.MagDisturbDetect(sensor, streamingPacket, calibrateMag);
sensor.attitudeHelper.CalculateQuaternion(sensor, streamingPacket, calibrateMag);
}
}
}
this.Invoke(new Action(UpdateAllConnectedChart));
}
顺带一提,其中一个线程由于某些未知原因(没有引发任何异常)而被卡在sensor.attitudeHelper.MagDisturbDetect(sensor, streamingPacket, calibrateMag);
上,它是第三方库中的一种方法。并且由于该问题线程锁定了lockObject1
,因此所有创建的新线程都无法在该锁定内运行代码...
因此,在这种情况下,使用取消标记,停止标志似乎不是终止线程的正确方法。我尝试了.abort()
方法,该方法当然会使终止过程变得不可预测,因此,它也不是一种好方法。并且Monitor.TryEnter
无法完成该作业,因为它会超时尝试获取锁的线程,而不是拥有该锁的问题主机。
我想做的是终止有问题的线程,并在超时时释放锁。如果有人可以告诉我如何实现一种可靠的方式来终止线程(SafeCreateProcessThread()
中的代码块)。
if (th.IsAlive)
{
// timeout
// terminate the thread and release the lock
}
谢谢。
线程卡在其中的代码:
标有//------->
public bool MagDisturbDetect(DSensor sensor, StreamingPacket streamingPacket, double[] calibratedMag)
{
if (lstMagXBuffer == null)
{
lstMagXBuffer = new List<double>();
lstMagYBuffer = new List<double>();
lstMagZBuffer = new List<double>();
}
if (lstRawMagXBuffer == null)
{
lstRawMagXBuffer = new List<double>();
lstRawMagYBuffer = new List<double>();
lstRawMagZBuffer = new List<double>();
}
bool disturbDetected = false;
int bufferLength = 200;
if (sensor.config.mag_sampling_frequency != "standby")
{
var x = Convert.ToInt32(sensor.config.mag_sampling_frequency.Replace("Hz", ""));
bufferLength = 2 * x;
}
double isDisturbed = 0;
magCalibrator magCalibrator = new magCalibrator();
if (lstMagXBuffer.Count >= bufferLength)
{
double[] magXBuffer = lstMagXBuffer.ToArray();
double[] magYBuffer = lstMagYBuffer.ToArray();
double[] magZBuffer = lstMagZBuffer.ToArray();
isDisturbed = magCalibrator.callisMagDisturbanceFcn(magXBuffer, magYBuffer, magZBuffer, 0.3f);
if (isDisturbed == 1)
{
disturbDetected = true;
}
else
{
disturbDetected = false;
}
//Console.WriteLine($"MagDisturbDetect {isDisturbed}");
//Console.WriteLine("------------------------------clear calibrated buffer");
lstMagXBuffer = new List<double>();
lstMagYBuffer = new List<double>();
lstMagZBuffer = new List<double>();
}
else
{
lstRawMagXBuffer.Add(streamingPacket.magnx);
lstRawMagYBuffer.Add(streamingPacket.magny);
lstRawMagZBuffer.Add(streamingPacket.magnz);
lstMagXBuffer.Add(calibratedMag[0]);
lstMagYBuffer.Add(calibratedMag[1]);
lstMagZBuffer.Add(calibratedMag[2]);
}
// DateTime dt = DateTime.Now;
if (disturbDetected)
{
double[] rawMagXBuffer = lstRawMagXBuffer.ToArray();
double[] rawMagYBuffer = lstRawMagYBuffer.ToArray();
double[] rawMagZBuffer = lstRawMagZBuffer.ToArray();
double[] gainOut = new double[] { 0 }, magXAfterCali = new double[] { 0 }, magYAfterCali = new double[] { 0 }, magZAfterCali = new double[] { 0 }, rmse = new double[] { 0 };
double[] gainIn = new double[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
double[] offsetIn = new double[] { 0, 0, 0 };
// ------> became stuck when executing magCalibrator.callCalibrateMagetometerLiveFcn(...)
magCalibrator.callCalibrateMagetometerLiveFcn(rawMagXBuffer, rawMagYBuffer, rawMagZBuffer, gainIn, offsetIn, 0.3f,
ref gainOut, ref sensor.offsetMagCalibrate, ref magXAfterCali, ref magYAfterCali, ref magZAfterCali, ref rmse);
lstRawMagXBuffer = new List<double>();
lstRawMagYBuffer = new List<double>();
lstRawMagZBuffer = new List<double>();
}
else
{
magCalibrator.callUpdateOffsetFcn((float)streamingPacket.magnx, (float)streamingPacket.magny, (float)streamingPacket.magnz, 0.3f,
sensor.offsetMagCalibrate[0], sensor.offsetMagCalibrate[1], sensor.offsetMagCalibrate[2], ref sensor.offsetMagCalibrate);
}
magDisturbed = disturbDetected;
return disturbDetected;
}