2016-10-11 6 views
0

コンポーネントでは、アプリケーションが責任を負う必要がある間にUDP経由でデータを受信する必要があるため、UDPリスニング用にこのコンポーネントクラス内にスレッドを作成しました。データが受信されると、2つの動作が20msの遅延でなければなりません。アクション1の後には常にアクション2を続ける必要があります。mutexを使用してスレッドとタイマーの経過イベントを制御する

私はタイマーとミューテックスインスタンスを作成しました。データを受け取った後、ミューテックスはロックされているため、アクション1は実行できませんが、アクション2は実行できません。タイマーが経過すると、イベントハンドラが呼び出され、2番目のアクションが処理され、ミューテックスが解放されます。それは理論上の計画です。

しかし、私はそれを解放しようとすると、ミューテックスがロックされていないというエラーが表示されます。

Imports System.Timers 

Public Class CriticalActionProcessor 
    Private mTimer As System.Timers.Timer 
    Private mTimerMutex As Threading.Mutex 

    Private mReceiveThread As Threading.Thread 

    Public Sub New() 
     ' do some initalizing 

     mReceiveThread = New Threading.Thread(AddressOf ProcessUDP) 
     mReceiveThread.IsBackground = True 
     mReceiveThread.Start() 

     mTimer = new Timer() 
     mTimerMutex = New Threading.Mutex() 
     AddHandler mTimer.Elapsed, Sub() 
             ' do some things, that must happen after some time 
             mTimerMutex.ReleaseMutex() ' here it throws an exception 
                    ' because mutex is not locked 
            End Sub 
    End Sub 

    Private Sub ProcessUDP 
     Dim udpReceiver = New UdpClient(5668) 
     Dim ipEndPoint = New IPEndPoint(IPAddress.Any, 5668) 

     While (True) 
      Dim receivedData As Byte() = udpReceiver.Receive(ipEndPoint) 
      ' check received data 
      mTimerMutex.WaitOne() 
      Fire() 
     End While 
    End Sub 

    Private Sub Fire() 
     ' do some things and after that start timer 
     mTimer.Interval = 20 
     mTimer.Start() 
    End Sub 
End Class 

ミューテックスは、UDPスレッドとタイマースレッドで共有されていないようです。タイマー経過ハンドラが呼び出される前に、Fire()メソッドが2回目に呼び出されないようにするにはどうすればよいですか?

+0

2つのスレッドを持つことができます.1つは、データを受信して​​キューに入れ、もう1つはキュー内のデータを処理します。 2つの動作の間に、タイマーの代わりに睡眠をとることができます。 –

答えて

0

問題

あなたの主な問題は、ここではどのようにミューテックスの仕事であなたの誤解です。ミューテックスはロックです。一度取り込んだスレッドは、それを取ったスレッドによってのみ解放されます。

トイレのロックを考えてください。もしJohnがそこに入って自分のものをロックしていたら、Arnoldがロックを解除する方法はありません...

これはあなたがやっていることです.1つのスレッド(ProcessUDP)がロックをとります。 ...それを解放しようとする)別のスレッド上

私の最初の推測では、タイマーやタイマーのためのサブ内部のあなたの2番目のアクションを呼び出す前に、あなたの最初のアクションを呼び出すことであろう解決策:

'In the sub new, this is actually the second action 
AddHandler mTimer.Elapsed, Sub() 
           'Do your second action here, 
           'since it will be called after the timer is done 
          End Sub 

'This would be the first action 
Private Sub Fire() 
    'Do your first action and after that start timer 
    mTimer.Interval = 20 
    mTimer.Start() 
End Sub 

この方法では、ミューテックスやロックを気にすることもありません。

関連する問題