質問者
複数スレッドでの Shared imgconv As System.Drawing.ImageConverter() 使用方法

質問
-
表題の件ですが、現在複数スレッドで非同期にByte→Imageへの変換、その逆を行いたいと思っております。
Shared imgconv As System.Drawing.ImageConverter()を使用するとimgconvがスレッド間で競合を起こし
エラーが発生しております。StaticなLockオブジェクトを指定することで回避はできましたが
Lockをしている時間は他のスレッドが待ち状態になってしまい変換時間に無駄が生じてしまいます。
コードは下記となります。
Shared imgconv As New System.Drawing.ImageConverter()
Shared lockObject As New Object() '
' バイト配列をImageオブジェクトに変換
Public Function ByteArrayToImage(ByVal b As Byte()) As Image
SyncLock lockObject
Dim sw As New Stopwatch
sw.Restart()
'Dim imgconv As New System.Drawing.ImageConverter
Dim img As Image = CType(imgconv.ConvertFrom(b), Image)
sw.Stop()
Console.WriteLine("ByteArrayToImage:" & sw.ElapsedMilliseconds & vbCrLf)
Return img
End SyncLock
End Functionお詳しい方が見えましたらマルチスレッドからのアクセス方法、もしくは他の変換方法(ConvertFromとConvertToの代わりになるもの)
をご教授願いたく、どうぞよろしくお願いいたします。
すべての返信
-
なぜImageConverterをsharedにして複数スレッド間で使いまわす必要があるのでしょう?
ImageConverterの説明には「この型のパブリック static (Visual Basic では Shared ) メンバーはスレッド セーフです。インスタンス メンバーの場合は、スレッド セーフであるとは限りません。 」と書かれているので、複数スレッドからの同時アクセスは保証されてません。
回避するなら、スレッド毎にImageConverterを作ればいいだけです。
Public Class Form1 Sub New() ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim buf As Byte() Using fs As System.IO.Stream = System.IO.File.OpenRead("test.jpg") ReDim buf(fs.Length) fs.Read(buf, 0, buf.Length) End Using For i = 0 To 10 Dim thread As New System.Threading.Thread(Sub() Dim imgconv As New ImageConverter ByteArrayToImage(buf, imgconv) End Sub) thread.Start() Next End Sub Public Function ByteArrayToImage(ByVal b As Byte(), Optional ByVal imgconv As System.Drawing.ImageConverter = Nothing) As Image If (imgconv Is Nothing) Then imgconv = New ImageConverter() End If Dim sw As New Stopwatch sw.Restart() Dim img As Image = CType(imgconv.ConvertFrom(b), Image) sw.Stop() Console.WriteLine("ByteArrayToImage:" & sw.ElapsedMilliseconds & vbCrLf) Return img End Function End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
-
ImageConverterクラスはTypeConverterの派生クラスとして、統一された変換方法を提供するためのものであり、内容的には Image.FromStream(New MemoryStream(b)) でしかありません。ImageConverterクラスを使うまでもないのでは?
-
gekka様
ご指示ありがとうございます。
おっしゃることはもっともで、すでにその方法も試してみましたが
やはりオブジェクトが重複する旨のエラーが発生しております。(Gekka様記載方法も試しました)
現在コーディングしているのはWWFの非同期なActivityを自作しております。
このActibity内にimgconvを使用する記述があるのですがActivity事態をワークフローに
並列に配置して2~3個のActibityを実行する際に発生してます。
Activityならではの、何か問題(インスタンスがNewできていない)のかなとは考えておりますが
原因がいまだにわかりません。
いかがでしょうか?