visual studio community 2017でC#を使っています。
環境はwin7 pro 64bitです。
非同期でWindows Formsのlistview項目追加するのを動かしくてinvokeで書きたいと思っています。
listviewに項目追加するのを書いています。
C#
1ListViewItem item = listview1.Items.Add("テスト");-----------A 2item.SubItems.Add("データ");---------------------------------B
Bはinvokeで書けそうですが、Aをinvokeで書く方法がいろいろ調べたんですが分かりませんでした。
Aは戻り値があるため分かりませんでした。
C#
1this.Invoke((MethodInvoker)(() => item.SubItems.Add("データ")));
Aをinvokeで書く方法を教えてもらえないでしょうか。
よろしくお願いします。
何を作っているのかと開発環境を質問欄を編集して追記してください。ListView というのは Windows Forms, WPF, ASP.NET Web Forms のいずれにもあるのですよ。
用語は正しく使いましょう。
×: リストビュー
〇: ListView
そもそもなんですが、「invokeで書きたい」というのはどういうことで、その理由は何ですか?
invokeで書く方法っていうより複数行のものをラムダ式で書くにはどうすればいいかって話かと思います。
「C# ラムダ式 複数行」あたりで検索すればいいかと
ListView というのは Windows Forms, WPF, ASP.NET Web Forms のいずれにもあるのですが、どれを作っているのか(どれでもなければ何を作っているのか)を質問欄を編集して書いてくださいと上のコメントでお願いしたつもりなのですが・・・
「invokeで書きたい」というのはどういうことで、その理由は何ですか?・・・には答えていただけないのですか? YAmaGNZ さんが言われるようにラムダ式を使って書くということですか? その理由は何ですか? XY 問題になってませんか?
非同期でlistviewを操作したいからです。編集で書き込んでいます。
> 非同期でlistviewを操作したいからです。
そのあたりをもっと具体的に書いてください。Windows Forms アプリということですから UI スレッドがあって、その UI スレッドで時間がかかる何らかの処置をすると処理が終わるまでフリーズしたようになるので、その何らかの処置を別スレッドで行うということには意味がありそうですがそういうことですか? そうだとして、それと「invokeで書きたい」というのとどうつながるのですか?
listviewを操作といってもlistviewに項目を追加するだけです。A、Bのように。それ以外の操作はありません。listviewに項目追加する件数が多い(数千件)ため時間がかかり非同期でと考えました。非同期でコントロールを制御する場合はinvokeすると思っていたので、listviewに項目追加するのにinvokeを適用しようと思いました。
> listviewに項目追加する件数が多い(数千件)ため時間がかかり非同期でと考えました。
そもそも数千件ものアイテムを ListView に表示してユーザーに見せることが意味があるのか疑問ですが、そこはとりあえず置いといて・・・
単純に以下のようにしてできないのですか? 数千件あるならこれを数千件繰り返すということでできるのでは?
this.Invoke((Action)(() => {
ListViewItem item = listview1.Items.Add("テスト");
item.SubItems.Add("データ");
}));
「invokeで書きたい」とか意味不明な表現をしているところからすると、やりたい事よりもまず非同期操作の基本から書籍なりネット記事なりを参照してお勉強するところがスタートラインでしょう。
自分が何をやろうとして、どこが問題で、何のためにその処理を書くのかをわかってなければ、いくら回答したところで理解できるように思えない。
大量のデータを追加したいという理由で非同期化して1件の追加をInvokeしてもほとんど高速化には繋がらないかと思います。
AddRangeを利用するなりしてまとめて追加することを考える方がいい気がします。
質問者さん、無言になってしまいましたが、やっぱり XY 問題だったのでしょうか?
時間がかかるのは ListView に項目を一つ追加するごとに画面描画が行われるからです。
BeginUpdate と EndUpdate を使い、適切なタイミングまで描画を行わないことで速くなります。
数千程度なら問題ないでしょう。
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.listview.beginupdate?view=net-5.0
YAmaGNZ さんのおっしゃるように AddRange を使えばこれが自動的に呼び出されるので、それで事足りると思います。
非同期での追加は、それが終わるまで操作できなくしなければいけないので、根本的な解決になりません。
もっと大量の場合には、仮想モードを使用します。
これなら項目をいくら追加しても問題ありません。
と、こういう感じに Invoke よりも良い方法が他にあるので、みなさん詳細を聞きたがっているんですよ。経験者の尋ねることには素直に答えるのが得策です。
非同期を含めいろいろと知識がないことで皆様にご迷惑をおかけしたと思っております。AddRangeを含め、もう一度考え直します。ありがとうございました。
表題の「listview項目追加をinvokeで書きたい」は止めて別の手段を考えるということにしたのだと理解していますが、そうであればこのスレッドはその旨書いてクローズしてください。
次回質問する際は XY 問題にならないよう、Y だけでなく X も質問に書くようお願いします。
あなたの回答
tips
プレビュー