[C#][Memo]Magick.Netの画像読み込みをByteArrayで行う時、並列で動かすと例外が発行される件とその対処

世の中にはMagick.NETというImageMagickをラップした便利なライブラリがあり私も利用しています。

利用している中である条件の時だけ例外が発行されるという事象に遭遇しました。
今回は、どういう状況で発生し、それをどうクリアしたのかという話です。

事象

MagickImageインスタンスのコンストラクションをByteArrayで行う時
特に並列で動かして無いとき正常に動作する。(以下サンプルコード)

    using (var image = new MagickImage(ImageByteArray)) //バイト配列を渡しているよ
    {
       //なんらかの処理
    }

しかしながら、並列で動作させる以下のコードだと、

Parallel.ForEach(Enumerable.Range(1, 100), _ =>
{
    using (var image = new MagickImage(ImageByteArray)) //バイト配列を渡しているよ
    {
       //なんらかの処理
    }
}

下記の例外が発行される。
このイメージフォーマットのデコーダが見つからないよ?と言っているんですね。
Parallelで回さなければちゃんと見つけてきてくれるのに・・・。

MagickMissingDelegateErrorException
Magick: no decode delegate for this image format `’ @ error/blob.c/BlobToImage/358

というわけで・・・

解決まで

調べているうちに、以下のサイトにたどりついた

http://magick.codeplex.com/discussions/447999
Unable to load ICO from a Stream or Byte array

パス指定だと読みこめて、Byte Arrayだと同じ例外が発行されるらしい。
状況が違うのと、今回私が対象にしているのは、ICOファイルではないく、PNGファイルなのだが試してみた。

//パスを指定してみる
Parallel.ForEach(Enumerable.Range(1, 100), _ =>
{
    using (var image = new MagickImage(FilePath))
    {
       //なんらかの処理
    }
}

確かに上記コードだと正常に動作する。
しかしながら、バイト配列で読ませたいの。

ということで、上記たどりついたページを見ると、MagickReadSettings を渡してやれよ。と書いてある。
ので、試してみた。

//パスを指定してみる
Parallel.ForEach(Enumerable.Range(1, 100), _ =>
{
   var readSettings = new MagickReadSettings
     {
         Format = MagickFormat.Png
     };

    using (var image = new MagickImage(ImageByteArray,readSettings)) //バイト配列とMagickReadSettingsを渡しているよ
    {
       //なんらかの処理
    }
}

とすると、確かに正常に動作した。
というわけで、結果、ちゃんと読み込み設定をして渡してあげれば、それをもとにdecodeしてくれるようです。

Share