- PR -

ListViewの背景色を変更した時のちらつきを防ぎたい

投稿者投稿内容
kamada
会議室デビュー日: 2005/09/14
投稿数: 6
投稿日時: 2005-09-27 17:30
遅くなりましたが経過を報告します。

こちらで書いたコードはご指摘のように基本が間違っていたようです。
申し訳ありません。

ご紹介頂いたページを参考にさせて頂いた上で、サブアイテム
単位で再描画を行うHongliangさんのコードを使うように修正して、
動作させてみました。

結果としてはサブアイテム単位で描画され、以前よりかなり滑らかに
動いているように見受けられます。しかしこれでも、数秒に1度
全体描画がかかります。

おそらくHongliangさんの環境では全体描画は起きていないと思われるので、
こちらの環境でのみ全体描画される原因について推測してみました。
こちらで実装しているのは100行5列程度の数値データ表をリアルタイムで
更新していくようなアプリなのですが、このアプリでは色を変更するのに
(Hongliangさんの実装で言うとDetailsListView#ChangeSubItemBackColorを呼び出すのに)、
別途スレッドを使用しておりまして、これが原因である可能性があります。

なぜ別スレッドにしているかというと、データが更新されたことを示すために
更新されたサブアイテムの背景色を2秒間だけ変更してまた元の色に戻すと
いうような動作をさせる為です。

class Form1
{
........
//別スレッド上で動作する色変更メソッド
//System.Threading.ThreadPoolクラスを介して呼び出されるように
//している
private void ChangeBackColorByThread(object listPoint)
{
ListPoint lp = (ListPoint)listPoint; //listPointは更新情報を詰めたオブジェクト
listView1.ChangeSubItemBackColor(lp.RowIndex,lp.ColumnIndex,Color.Red);
System.Threading.Thread.Sleep(2000);
listView1.ChangeSubItemBackColor(lp.RowIndex,lp.ColumnIndex,Color.White);
}
}

ちなみに、上と同じ条件で、色を戻すのをやめて同一スレッド上で動かすと
全体描画は起きない(起き難い?)ようです。まだはっきりと因果関係は
わかっていないのですが、何かご指摘があればお願いします。こちらでも
進展ありましたら、またご報告させて頂きます。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-09-27 18:52
コントロールはスレッドセーフではありませんので、別スレッドから直接コントロールを操作してはいけません。その際の動作は保証されません。
別スレッドからコントロールを操作するには、ControlクラスのInvokeメソッド(同期的に操作)またはBeginInvokeメソッド(非同期で操作)を使用して、メインスレッド(コントロールを作成したスレッド)に操作を依頼する、と言う形を取る必要があります。

ところで、10回/sも変更が発生するとなると、下手するとスレッドプールを使い切ってしまいませんか?
//通常25が上限でしたっけ。
プール内で最低2秒は待機しなければならないわけですし。
この場合Threadクラスを使った方が良いような気がします。
.NET 1.0/1.1だとParameterizedThreadStartを使えないので、ネストクラスを一つ作るかなにかしなければなりませんが。

スキルアップ/キャリアアップ(JOB@IT)