Как установить таймаут для блокировки (которая была получена)? - PullRequest
0 голосов
/ 24 января 2019

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