【发布时间】:2019-08-06 05:17:26
【问题描述】:
我有一个 .net DLL,它调用了一个非线程安全的 c++ DLL。 .NET DLL 在 IIS 中运行。 IIS 应用程序池加载两个 DLL 的单个副本,并且当两个浏览器会话同时调用 .NET DLL 时,C++ DLL Ralph 就在它的鞋子上。在某些情况下,它会导致应用程序池失败,而在其他情况下,我会收到一个可捕获的错误。
我尝试使用 Monitor 类来解决我的问题:
Private objSync As Object = New Object
.
.
.
.
Monitor.Enter(objSync)
editsErrorHandler(MycPlusPlusCall(_intsmfID, _strEditSetTag, _strEditLayoutTag, strNAACCRRecord,
EE_SKIPFAIL, intErrCount, _ptrThis, _ptrEditsMessagerHandler),
"MycPlusPlusCall")
objMessageTransport.intMstErrorCount = intErrCount
objMessageTransport.objMstMessages = _objErrorMessages
' Debug.Print("intErrCount=" & intErrCount)
Monitor.Exit(objSync)
MycPlusPlusCall 是 c++ DLL 调用。
这似乎没有影响。
这是我第一次尝试调用非线程安全的 DLL。
如何强制应用程序池中的多个调用等待上一个调用完成?
编辑:
我将 Monitor 提升了一级,几乎每次都成功地让 W3WP 崩溃。当它崩溃时,我在 w3wp 上得到 AppCrash,模块是 c++ DLL。
上面引用的 .NET DLL 由“上方”的 DLL 调用,因此我将 Monitor.Enter & Exit 移至该级别。新的和改进的代码看起来像;
Private Function processRecord(ByVal strInterRecordEditsName As String, _
ByVal objConnection As OracleConnection) As Integer
Dim strNAACCRRecord As String = buildNAACCRRecord(_objRecord)
' Dim strNAACCRRecord As String = _objRecord("NAACCR_RECORD")
Dim objErrorMessageTransport As ACEEdits50.EditMessageTransport
Dim intErrCount As Integer = 0
Dim objErrorMessages As List(Of ACEEdits50.EditMessage) = New List(Of ACEEdits50.EditMessage)
Dim strDebug As String = "Section 10"
On Error GoTo processRecordError
Monitor.Enter(_objACEEdits)
' Here is where the heavy lifting is done.
objErrorMessageTransport = _objACEEdits.runEdits(strNAACCRRecord & Space(_intNAACCRRecordSize - strNAACCRRecord.Length))
Monitor.Exit(_objACEEdits)
编辑 2:
所以我删除了较高的“Monitor.Enter/Exit”并按照下面的建议将其替换为 SyncLock,并添加了使对象“私有共享”的选项 所以代码看起来像;
Public Class ACEEdits50
Public Sub New()
End Sub
.
.
.
.
Private Shared objSync As Object = New Object
.
.
.
.
Public Function runEdits(ByVal strNAACCRRecord As String) As EditMessageTransport
.
.
.
.
SyncLock objSync
editsErrorHandler(Edit_RunEdits(_intsmfID, _strEditSetTag, _strEditLayoutTag, strNAACCRRecord,
EE_SKIPFAIL, intErrCount, _ptrThis, _ptrEditsMessagerHandler),
"Edit_RunEdits")
objMessageTransport.intMstErrorCount = intErrCount
objMessageTransport.objMstMessages = _objErrorMessages
' Debug.Print("intErrCount=" & intErrCount)
End SyncLock
我仍然遇到同样的 appCrash。
【问题讨论】:
-
如何使用互斥锁?
-
vb.net 有
SyncLock -
你确定这不起作用吗?除了将代码放在 try/finally 块中(以便在所有情况下都调用 Monitor.Exit),这是标准模式。正如@DanielA.White 指出的那样,语言提供的
SyncLock关键字(或C# 中的lock)将为您执行此操作。 -
你也应该使用相同的引用来锁定
-
objSync 是否需要标记为静态?很难判断这是否在实例类中,但如果是,每个实例都可能有一个 objSync。