0

我正在就我的测试的有效性寻求一些第二意见。

简而言之,我使用 MMF 来模拟从 WinForms 客户端到 Windows 服务的同步方法调用。由于此处讨论的原因,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
4

0 回答 0