私のテストの有効性について、セカンドオピニオンを求めています。
簡単に言うと、MMF を使用して、WinForms クライアントから Windows サービスへの同期メソッド呼び出しをシミュレートしています。here で説明されている理由により、WCF も名前付きパイプもこれには適していません。
私のプロトタイプでは、2 つの単純なアプリケーションを作成しました。コンソール アプリは WinForms の「クライアント」を表し、WinForms アプリは WinService の「サーバー」を表します。
2 つの主な問題を克服する必要がありました。1) サーバーのタイマーが 3 秒に 1 回しか起動しない、2) OS がミューテックスを取得して解放するのに少なくとも 1 秒かかるようです。この 2 番目の点が気になります。プロセスは瞬時に行われると思っていたのですが、どうやら私は間違っているようです。
これら 2 つの問題に対処するために、私は Thread.Sleep を使用しました。サーバーのタイマーを 2 秒間待機し、mutex 処理を 1 秒間待機します。これらの間隔より短い間隔では、断続的な読み取り/書き込み同期エラーが発生します。もちろん、コードを自由に微調整して、独自の結果を取得してください。
私のテストは、サーバーで「メソッド」を「呼び出し」、応答をログ ファイルに書き込む、クライアントでの 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