<ソースの概略> 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 Public Class ShipArray
〜〜〜 中略 〜〜〜
Public Sub DrawShip() If ShipsLock Then Exit Sub '追加・削除時にロックが掛かっている時は描画しない For Each sp As Ship In ships sp.setPosition() '緯度・経度からX,Yを計算し、描画する ← ※イベントで描画させるとここでエラーが出る。 Next End Sub
End Class
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 Class Ship Private WithEvents shipImage As New PictureBox
〜〜〜 中略 〜〜〜
Private Sub setPosition() <地図の描画範囲(緯度・経度)から地図上のX,Yを計算> position = New Point(地図上のX, 地図上のY) Dim pnt = New Point(shipImage.Width / 2.0F, shipImage.Height / 2.0F) mF.Invoke(New posInvoker(AddressOf privateSetShipPos), New Object() {position - pnt}) mF.Invoke(New visInvoker(AddressOf shipImgVisible), New Object() {True}) End If End Sub
Private Sub privateSetShipPos(ByVal pos As Point) shipImage.Location = pos End Sub
Private Sub shipImgVisible(ByVal visible As Boolean) shipImage.Visible = visible End Sub
End Class 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Class frmMain
〜〜〜 中略 〜〜〜
Private Sub MpgMap_Paint(sender As Object, e As PaintEventArgs) Handles MpgMap.Paint If Not MpgMap.Drawable() Then Exit Sub 'main.DrawShip() ← コメントを外すとShipArrayクラスでエラー End Sub
End Class 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
2018/01/19(Fri) 15:01:06 編集(投稿者)
■No33786に返信(Azuleanさんの記事)
重ね重ねのご参考、ありがとうございます。
元々VB6.0でプログラムを組んでいたので、
オブジェクトとかスレッドの意味があまり良くわかっていないせいもあるとは思いますが
ロックの掛け方についてはまだまだ勉強が足りず、
いろいろ検索するのですが、『 ロックオブジェクト 』
としか書いてない記事がほとんどで、
どうしてそのオブジェクトでロックが掛けられるのか
また、どのオブジェクトで掛けるのが一番良いのかを
いまいち理解していません^^;
例えば、
SyncLock Me
SyncLock ArrayList.SyncRoot
ご紹介頂いた記事(http://www.atmarkit.co.jp/ait/articles/0505/25/news113.html)内の
SyncLock Bank
上記3つは何となくは解るのですが、
ロックオブジェクトを新たに作ってロックする…
(今回もこの方法でやっていますが…)
と言うのがいまいちピンと来ていません^^;
ただ、いろんな番所からロックを掛けられるのは便利なのかな…と言う認識です。
(Public Propertyにすればの話)
この記事を書きながら考えたのですが、
1つのオブジェクトに多数のメソッドがある場合、
SyncLock Meでロックしてしまうと、
ロックしたオブジェクトの他のメソッドもロックが掛かり、
アクセス出来なくなるので、下の様なロックを掛ける…
…と言う認識でよろしいでしょうか^^?
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Private ShipsLockObject As Object = New Object()
Private _ShipsLock As Boolean
Private Property ShipsLock As Boolean
Set(value As Boolean)
SyncLock ShipsLockObject
_ShipsLock = value
End SyncLock
End Set
Get
SyncLock ShipsLockObject
Return _ShipsLock
End SyncLock
End Get
End Property
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
ただ、最終的には
>DrawShip の For Each 実行中に別スレッドから ships を変更されないようにきちんと排他する(ロックする・保護する)か、>列挙するコレクションのコピーを作ってください。
との事だったので、船舶情報を途切れなく受信すると描画されないと思い、
コレクションのコピーを作りました。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
#Region "登録されている全船舶を返す"
''' <summary>
''' 登録されている全船舶を返す
''' </summary>
''' <returns>全船舶(Ships)</returns>
Public Function getShips() As ArrayList
Console.WriteLine("Execute ShipArray.getShips() As ArrayList")
Return Ships.Clone
End Function
#End Region
Public Sub DrawShip()
Console.WriteLine("Execute ShipArray.DrawShip()")
Dim sps As New ArrayList()
sps = getShips()
For Each sp As Ship In sps
sp.ShipInvisible()
Next
For Each sp As Ship In sps
sp.checkPosition()
Next
Dim cnt As Integer = 0
For Each s As Ship In sps
If s.getShipImageVisible Then cnt += 1
Next
mF.TS_ShipCount.Text = cnt
sps = Nothing
End Sub
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
オブジェクト指向もマルチスレッドも奥が深すぎです><