मैं PInvoke तकनीक का उपयोग करके .NET Framework 4.6.1 a C++ dll (CoolProp लाइब्रेरी) से कॉल कर रहा हूं .

निम्नलिखित सी # कोड:

[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++ लाइब्रेरी हो सकती है (रेपो में किसी समस्या से ऐसा नहीं लगता है link< /ए>)?

0
EduBic 26 मार्च 2020, 20:21

1 उत्तर

सबसे बढ़िया उत्तर

निश्चित रूप से सी ++ लाइब्रेरी स्वयं थ्रेड सुरक्षित नहीं है, उदाहरण के लिए एक स्थिर त्रुटि स्ट्रिंग है https://github.com/CoolProp/CoolProp/blob/master/src/CoolProp.cpp#L59 जिसे एक साथ अपवाद हैंडलिंग और कुछ अन्य स्थानों द्वारा सेट किया जा सकता है। यदि यह कई थ्रेड्स पर सेट है तो यह एक विफलता मोड हो सकता है जिसके परिणामस्वरूप स्मृति भ्रष्टाचार होता है, यह निश्चित रूप से अपरिभाषित व्यवहार है और इससे बचा जाना चाहिए।

2
Pete Kirkham 26 मार्च 2020, 17:39