スレッド描画のまとめ

アイコン取得やネットワークパスのタイムアウト待ちなどで入力できない状態になるのを回避するために、描画をスレッド化できるようにしています。ネットワークパス等を使ってないなら、そんなに深く考える意義のあるものではありません。
描画される部位は、Edit/ListのIcon/Textの4つ。どうスレッド化するかをConfigのDraw.(Edit|List).(Icon|Text).Thread.Enableで設定可能にしてあります。それらをデフォルト値とし、Event.Get(Edit|List)ThreadEnableで、描画毎に指定が可能です。
スレッドには、MultiとSingleがあり、メインスレッドとは別の描画スレッドを、1つだけにするか描画毎にするかが選べます。デフォルトはMultiであり、Giraffe.EnableSingleThreadDrawing(true)でSingleになります*1。Thread.Enableの値をマイナスにすることで設定と逆になります。
Multiの場合、同時に多くのリソースにアクセスするため、多少動作に不安定な部分が生じ、描画が前後したり、リソースの取得に失敗したりしますが、全体が一斉に描画されるので、感覚的には高速です。
Singleなら、描画は順番にされ、それが前後したりすることはありませんが、時間のかかる処理に引っかかった場合、その後の描画はそれが終わるまでされません。
Thread.Enableの値から1を引いたミリ秒数待って並列化します。描画の別スレッド化自体は描画開始時にされており、ただメインスレッドは待つだけであり、メインスレッドで描画がされるわけではありません。
SingleでThread.Enableが2以上の場合、Singleの描画スレッドからさらに描画スレッドを描画毎に生成し、終了を待ち、指定時間内に終了しなかった場合に並列化します。Multiの待ち処理と違い、メインスレッドは待ちませんので、入力不能にはなりません。

問題点

  • Edit-Textの描画をメインスレッドかメインスレッドが待つ間にやらないと、キャレットの軌跡が一つだけ残ります。キャレット移動時にキャレットを隠すとか再描画とかあれこれ試しましたが、連続移動時の軌跡も消えてしまうなど、いい結果にはなりませんでした。
  • List-Textの描画をメインスレッドが待つようにすると、なぜかList-Iconも待つようになります。アイコン取得APIがメインスレッドと通信してるようです。
  • devmgmt.mscにEdit-IconとList-Iconが同時アクセスするとエラーに。Shell Icon Hookの問題のようです。Shell関係のフックは環境にもよりますし、もう描画中のエラーは全て無視してその描画を中止するだけにしています。

描画、スレッド、シェルアイコン取得等、Windowsの仕様の部分が大きいので、あまり深入りする気はありません。

*1:settings\setup\(DRAW)SingleThread