我正在寻求关于我的考试有效性的第二意见。
简而言之,我使用MMF来模拟从WinForms客户端到Windows服务的同步方法调用。由于讨论here的原因,WCF和命名管道都不适合这种情况。
对于我的原型,我创建了两个简单的应用程序 - 一个控制台应用程序代表WinForms'客户端',一个WinForms应用程序代表WinService'服务器。'
我必须克服两个主要问题:1)服务器的计时器每三秒才触发一次,并且2)操作系统似乎需要至少一整秒才能获取然后释放互斥锁。第二点让我很好奇。我认为这个过程是即时的,但显然我错了。
为了适应这两个问题,我使用了Thread.Sleep - 等待服务器计时器的两秒钟和等待互斥锁处理的一秒钟。任何小于这些的间隔都会导致间歇性读/写同步失败。当然可以随意调整代码以获得自己的结果。
我的测试由客户端中的30,000次迭代循环组成,该循环“调用”服务器中的“方法”并将响应写入日志文件。目前我正在迭代~22,500没有任何错误。
我的问题:有没有人看到我的测试有任何问题?鉴于我的MSDN帖子(上面链接)中指出的要求,到目前为止我的结果是否表明设计稳定?
那就是说,如果我的架构可以改进,我会非常有兴趣听到它。
以下是代码:
控制台(客户端)
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Imports System.Text
Imports System.Security.Cryptography
Module Main
Sub Main()
Dim _
sForward,
sReverse,
sOutput As String
Console.WriteLine("Enter a string to reverse:")
For iCount As Integer = 0 To 29999
sForward = GetRandomString(7)
sReverse = ReverseString(sForward)
sOutput = sForward & " => " & sReverse
File.AppendAllText("Output.log", sOutput & vbCrLf)
Console.WriteLine(sOutput)
Thread.Sleep(1000)
Next
Console.ReadLine()
End Sub
Private Function GetRandomString(Length As Integer) As String
Dim sSeedText As String
Dim oBuilder As StringBuilder
Dim aBuffer As Byte()
Dim oCrypto As RNGCryptoServiceProvider
sSeedText = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
oBuilder = New StringBuilder
aBuffer = New Byte(Length - 1) {}
oCrypto = New RNGCryptoServiceProvider
oCrypto.GetNonZeroBytes(aBuffer)
For Each bByte As Byte In aBuffer
oBuilder.Append(sSeedText.Chars(bByte Mod sSeedText.Length))
Next
Return oBuilder.ToString
End Function
Private Function ReverseString(Data As String) As String
Dim lIsOwner As Boolean
Dim iLength As Integer
Dim aData As Byte()
aData = Encoding.Unicode.GetBytes(Data)
iLength = aData.Length
Using oFile As MemoryMappedFile = MemoryMappedFile.CreateNew("{99EC7026-0059-4D48-99B1-B400BDACBDD8}", 1024)
Using oMutex As New Mutex(True, "{35C4F5C6-874B-4536-901A-D5382B7E2B9C}", lIsOwner)
'*=====================================================================
' Wait for the server's Timer.Tick event to fire
'*=====================================================================
Thread.Sleep(2000)
'*=====================================================================
Using oStream As MemoryMappedViewStream = oFile.CreateViewStream(0, 0)
Using oWriter As New BinaryWriter(oStream)
oWriter.Write(iLength)
oWriter.Write(aData)
End Using
End Using
oMutex.ReleaseMutex()
'*=====================================================================
' Wait for the server to acquire and then release the mutex
'*=====================================================================
Thread.Sleep(1000)
'*=====================================================================
oMutex.WaitOne()
Using oStream As MemoryMappedViewStream = oFile.CreateViewStream(iLength + 4, 0)
Using oReader As New BinaryReader(oStream)
With oReader
aData = .ReadBytes(.ReadInt32)
End With
End Using
End Using
oMutex.ReleaseMutex()
End Using
End Using
Return Encoding.Unicode.GetString(aData)
End Function
End Module
WinForms(服务器)
'*=============================================================================
'
' Add a ListBox
' Add a Background Worker
' Add a Windows Forms Timer
' Interval = 3000
' Enabled = True
'
'*=============================================================================
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.ComponentModel
Imports System.Threading
Imports System.Text
Public Class Main
Private Sub tmrTimer_Tick(Sender As Object, e As EventArgs) Handles tmrTimer.Tick
Dim lIsOpen As Boolean
Dim oFile As MemoryMappedFile
tmrTimer.Stop()
Try
lIsOpen = True
oFile = MemoryMappedFile.OpenExisting("{99EC7026-0059-4D48-99B1-B400BDACBDD8}")
bgwWorker.RunWorkerAsync(oFile)
Catch ex As FileNotFoundException
lIsOpen = False
End Try
If Not lIsOpen Then
tmrTimer.Start()
End If
End Sub
Private Sub bgwWorker_DoWork(Sender As Object, e As DoWorkEventArgs) Handles bgwWorker.DoWork
Dim iLength As Integer
Dim sData As String
Dim aData As Byte()
Using oFile As MemoryMappedFile = e.Argument
Using oMutex As Mutex = Mutex.OpenExisting("{35C4F5C6-874B-4536-901A-D5382B7E2B9C}")
oMutex.WaitOne()
Using oStream As MemoryMappedViewStream = oFile.CreateViewStream(0, 0)
Using oReader As New BinaryReader(oStream)
With oReader
aData = .ReadBytes(.ReadInt32)
End With
End Using
End Using
sData = Encoding.Unicode.GetString(aData)
aData = Encoding.Unicode.GetBytes(New String(sData.Reverse.ToArray))
iLength = aData.Length
Using oStream As MemoryMappedViewStream = oFile.CreateViewStream(iLength + 4, 0)
Using oWriter As New BinaryWriter(oStream)
oWriter.Write(iLength)
oWriter.Write(aData)
End Using
End Using
oMutex.ReleaseMutex()
End Using
End Using
e.Result = sData
End Sub
Private Sub bgwWorker_RunWorkerCompleted(Sender As Object, e As RunWorkerCompletedEventArgs) Handles bgwWorker.RunWorkerCompleted
lstArguments.Items.Add(e.Result)
tmrTimer.Start()
End Sub
End Class