Я недавно работаю над многопоточным проектом и столкнулся с проблемой.SafeCreateProcessThread();
вызывается каждые 220 мс, пока датчик работает.
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;
}