Параллельные вызовы библиотеки C ++, обернутые PInvoke, вызывают System.AccessViolationException - PullRequest
0 голосов
/ 26 марта 2020

Я звоню из. NET framework 4.6.1 в C ++ dll ( Библиотека CoolProp ) с использованием технологии PInvoke.

Следующий C# код:

[DllImport("CoolProp", EntryPoint = "CSharp_PropsSI")]
public static extern double PropsSI(string Output, string Name1, double Prop1, string Name2, double Prop2, string Ref);

упаковывает объявление одной из основных функций библиотеки.

Когда она вызывается в однопоточной среде, все в порядке. Проблема возникает, когда я пытался вызвать эту внешнюю функцию параллельно, используя System.Threading.Tasks:

[TestMethod]
public async Task TestAsyncMethod()
{
    double tco = 30;
    string refrigerant = "R134a";

    var t1 = Task.Run(() => CoolProp.PropsSI("P", "T", tco + 273.15, "Q", 0.0, refrigerant));
    var t2 = Task.Run(() => CoolProp.PropsSI("P", "T", tco + 273.15, "Q", 0.0, refrigerant));

    var res = await Task.WhenAll(t1, t2);

    Assert.AreEqual(res[0], res[1]);
}

При выполнении вышеописанного модульного теста возникает следующее исключение:

Message: 
    Test method XRACModel_UnitTest.CoolingCircuitTest.TestAsyncMethod threw exception: 
    System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Stack Trace: 
    CoolPropPINVOKE.PropsSI(String jarg1, String jarg2, Double jarg3, String jarg4, Double jarg5, String jarg6)
    CoolProp.PropsSI(String Output, String Name1, Double Prop1, String Name2, Double Prop2, String FluidName) line 141
    CoolingCircuitTest.Method(Double tco, Double tev, Double sbc, String refrigerant) line 226
    <>c__DisplayClass3_0.<TestAsyncMethod>b__0() line 214
    Task`1.InnerInvoke()
    Task.Execute()
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    TaskAwaiter`1.GetResult()
    <TestAsyncMethod>d__3.MoveNext() line 217
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    ThreadOperations.ExecuteWithAbortSafety(Action action)

В чем причина проблемы? Почему использование одного потока нормально, но не в многопоточности? Может ли это быть библиотека C ++ (из-за проблемы в репо, похоже, не ссылка )?

1 Ответ

2 голосов
/ 26 марта 2020

Конечно, библиотека C ++ сама по себе не является поточно-ориентированной, например, есть строка c error error https://github.com/CoolProp/CoolProp/blob/master/src/CoolProp.cpp#L59, которая может быть одновременно установлена ​​обработкой исключений и несколькими другими местами. Если это установлено в нескольких потоках, это может быть режим сбоя, который приводит к повреждению памяти, это, безусловно, неопределенное поведение, и его следует избегать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...