在.NET中,如何保护一段代码不同时执行两次 我有一个.NET DLL,它调用一个不是线程安全的C++ DLL。.NET DLL在IIS中运行。IIS应用程序池加载DLL的单个副本,当两个浏览器会话同时调用.NdDLL时,其上的C++ DLL拉尔夫就在其上。在某些情况下,它会导致应用程序池失败,在其他情况下,我会得到一个可捕获的错误
我尝试使用Monitor类来解决我的问题,如:在.NET中,如何保护一段代码不同时执行两次 我有一个.NET DLL,它调用一个不是线程安全的C++ DLL。.NET DLL在IIS中运行。IIS应用程序池加载DLL的单个副本,当两个浏览器会话同时调用.NdDLL时,其上的C++ DLL拉尔夫就在其上。在某些情况下,它会导致应用程序池失败,在其他情况下,我会得到一个可捕获的错误,.net,vb.net,.net,Vb.net,我尝试使用Monitor类来解决我的问题,如: Private objSync As Object = New Object . . . . Monitor.Enter(objSync) editsErrorHandler(MycPlusPlusCall(_intsmfID, _strEditSetTag, _strEditLayoutTag, strNAACCRRecord,
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)
MycPulsPulsCalk是C++ DLL调用。< /P> 这似乎没有影响
这是我第一次尝试调用非线程安全DLL 如何强制应用程序池中的多个调用等待上一个调用完成 编辑: 我将显示器向上移动了一级,并成功地使W3WP几乎每次都崩溃。当崩溃时,我在W3WP上得到崩溃,模块是C++ DLL。 上面引用的.NET DLL是由“上面”的DLL调用的,因此我将监视器移动到该级别。请输入并退出该级别。新的和改进的代码如下所示 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)
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
编辑2:
因此,我删除了较高的“Monitor.Enter/Exit”,并按照下面的建议将其替换为SyncLock,添加了使对象“private shared”的选项,使代码看起来像
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)
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。这样试试
Private Shared protectIt As New Threading.AutoResetEvent(True)
Private Sub TestSimul()
protectIt.WaitOne() 'block forever
'
'code being protected
' when done
protectIt.Set()
End Sub
这样试试看
Private Shared protectIt As New Threading.AutoResetEvent(True)
Private Sub TestSimul()
protectIt.WaitOne() 'block forever
'
'code being protected
' when done
protectIt.Set()
End Sub
您可以使用命名互斥体,该互斥体用于在同一操作系统中的进程之间进行同步
Public Class ACEEdits50
Public Function runEdits(ByVal strNAACCRRecord As String) As EditMessageTransport
Using m = New Threading.Mutex(False, "ACEEdits50")
While Not m.WaitOne(20000) ' wait 20 seconds for mutex
Console.WriteLine("Waiting for mutex")
End While
editsErrorHandler(Edit_RunEdits(_intsmfID, _strEditSetTag, _strEditLayoutTag, strNAACCRRecord, EE_SKIPFAIL, intErrCount, _ptrThis, _ptrEditsMessagerHandler), "Edit_RunEdits")
objMessageTransport.intMstErrorCount = intErrCount
objMessageTransport.objMstMessages = _objErrorMessages
m.ReleaseMutex()
End Using
End Function
End Class
有关C#中的更多参考信息,请参阅。您可以使用命名互斥体,用于在同一操作系统中的进程之间进行同步
Public Class ACEEdits50
Public Function runEdits(ByVal strNAACCRRecord As String) As EditMessageTransport
Using m = New Threading.Mutex(False, "ACEEdits50")
While Not m.WaitOne(20000) ' wait 20 seconds for mutex
Console.WriteLine("Waiting for mutex")
End While
editsErrorHandler(Edit_RunEdits(_intsmfID, _strEditSetTag, _strEditLayoutTag, strNAACCRRecord, EE_SKIPFAIL, intErrCount, _ptrThis, _ptrEditsMessagerHandler), "Edit_RunEdits")
objMessageTransport.intMstErrorCount = intErrCount
objMessageTransport.objMstMessages = _objErrorMessages
m.ReleaseMutex()
End Using
End Function
End Class
有关C#中的更多参考信息,请参阅。如何使用互斥锁?vb.net具有
SyncLock
功能,您确定这不起作用吗?除了将代码放入try/finally块(以便在所有情况下都调用Monitor.Exit)之外,这是标准模式。正如@DanielA.White所指出的,C#中提供的SyncLock
关键字(或lock
)语言可以为您实现这一点。您还应该使用相同的引用锁定objSync是否需要标记为静态?很难说这是否在实例类中,但如果是,每个实例可能都有一个objSync。使用互斥锁怎么样?vb.net有同步锁
你确定这不起作用吗?除了将代码放入try/finally块(以便在所有情况下都调用Monitor.Exit)之外,这是标准模式。正如@DanielA.White所指出的,C#中提供的SyncLock
关键字(或lock
)语言可以为您实现这一点。您还应该使用相同的引用锁定objSync是否需要标记为静态?很难判断这是否在实例类中,但如果是,每个实例可能都有一个objSync。我尝试了@dbasnett定义的Threading.AutoResetEvent(True),没有运气。同样的结果。我尝试了@dbasnett定义的Threading.AutoResetEvent(True),没有运气。同样的结果。我确实使用了互斥锁,不完全是你的代码,但它似乎可以工作。其他一些解决方案也可能奏效。我这样说的原因是,有人告诉我,对DLL的一些调用是线程安全的,而其他调用则不是。我只是想保护那些我被告知有问题的人。最后,我将所有对DLL的调用包装在一个互斥体中,它起了作用。我确实使用了互斥体,不完全是您的代码,但它似乎起了作用。其他一些解决方案也可能奏效。我这样说的原因是,有人告诉我,对DLL的一些调用是线程安全的,而其他调用则不是。我只是想保护那些我被告知有问题的人。最后,我将所有对DLL的调用包装在一个互斥对象中,它成功了。