Ошибка PInvoke FatalExecutionEngineError в другом потоке

#c#

Вопрос:

мой код работает нормально, но через 5-10 минут я получаю следующую ошибку;

Помощник по управляемой отладке «FatalExecutionEngineError»: «Среда выполнения обнаружила фатальную ошибку. Адрес ошибки был 0x641ad419, в потоке 0x5d0c. Код ошибки 0xc0000005. Эта ошибка может быть ошибкой в CLR или в небезопасных или неподтверждаемых частях пользовательского кода. Распространенные источники этой ошибки включают ошибки маршалинга пользователей для COM-взаимодействия или PInvoke, которые могут привести к повреждению стека.

Вызывается из разных потоков;

 InvokeUtil.getInstance.Calculate(localVal);
 

Мой Код;

 public class InvokeUntil
{
    private IntPtr m_object = IntPtr.Zero;
    private static InvokeUntil Self;

    private InvokeUntil()
    {
        this.m_object = InvokeUntil.DllCreateInstance();
    }

    [DllImport("xDll")]
    private static extern IntPtr DllCreateInstance();

    [DllImport("xDll")]
    private static extern void DllDisposeInstance(IntPtr CSObject);

    [DllImport("xDll")]
    private static extern void DllCalculate(IntPtr pCSObject, byte[] pCurrentData, uint[] pResult);


    public static InvokeUntil getInstance
    {
        get
        {
            if (InvokeUntil.Self == null)
                InvokeUntil.Self = new InvokeUntil();
            return InvokeUntil.Self;
        }
    }

    public void Calculate(uint[] EffVal)
    {
        InvokeUntil.DllCalculate(m_object, Data.MyData, EffVal);
    }
}
 

Комментарии:

1. На первый взгляд, я бы предположил, что это может быть проблемой параллелизма. Я вижу, что DLL поддерживает DllCreateInstance метод, который, по-видимому, предполагает, что он поддерживает какое-то состояние. Является ли вызов DllCalculate потокобезопасным в DLL? Я бы предположил, что нет

2. @Martin Очевидно, что я не могу видеть содержимое библиотеки dll. Но ты имеешь в виду, что я должен позвонить? ; InvokeUtil.DllDisposeInstance (m_object);

3. Я имею в виду, что экземпляр m_object не является потокобезопасным, поэтому вызов его более одного раза одновременно вызовет проблему параллелизма.

4. Поскольку это прерывистый сбой, обычно происходит одна из двух вещей: 1) Это проблема выравнивания. Вашему приложению предоставляется диапазон памяти, который может быть измерен в байтах. Если параметры компилятора не настроены в соответствии с dll, вы можете превысить объем памяти на несколько байтов, если режим выравнивания (1,2,4,8 байта) установлен правильно 2) Проблема в коде dll.

5. DllCalculate() нельзя безопасно записать, он понятия не имеет, насколько большими могут быть массивы. Запись за пределами массива приводит к повреждению кучи GC, что в конечном итоге приводит к срабатыванию FEEE, когда сборщик мусора замечает повреждение. Исправьте это, добавив параметр, который передает EffVal. Длина, так что теперь возможна правильная проверка ошибок.