同步MMF测试

时间:2012-10-14 22:42:43

标签: .net vb.net architecture

我正在寻求关于我的考试有效性的第二意见。

简而言之,我使用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

0 个答案:

没有答案