如何为锁定(已获取)设置超时?

时间:2019-01-24 01:16:23

标签: c# multithreading winforms deadlock

我最近正在处理一个多线程项目,遇到一个问题。 只要传感器在流式传输,就会每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;
    }

0 个答案:

没有答案