質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

3回答

7893閲覧

BackgroundWorkerを使って非同期をしたい

chintao1224

総合スコア155

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2019/07/06 01:06

vb2017 Community版を使っています。
BackgroundWorkerというのがあるのを知り、使ってみようと思っているのですが。。。
どう使うべきか、どの方法が一番軽くなるか悩んでいます。

Form1:データの検索や更新や削除などユーザ様がいつもつかう画面を想定しています。(まだ何も決まっていません)

Form2:Form1からボタンクリックで呼び出される画面で、大量のデータを作成する(CSVを作成してDBにInsertしてUpdateする)ように考えていて、大量のCSVを作成するタイマー1、大量Insertするタイマー2、大量Updateするタイマー3を想定しています。
大量は2万件を想定しています。
大量のデータを作成する処理はロード時にそれぞれのタイマーを動かし呼び出されます。
Form2はユーザ様が意識する画面ではないため、最小化しておくつもりです。

BackgroundWorkerですが、Form2を呼び出すというのに使うべきでしょうか、それともForm2のタイマー1、タイマー2、タイマー3で処理を呼び出すときに使うべきでしょうか?
(Form2を呼び出すのに使った場合、呼び出した後のタイマー1、タイマー2、タイマー3の処理も非同期になるのかなという考えがあり、Form2を呼び出すのに使えばよいかと考えました)
どちらが軽くなるのでしょうか?

大量のデータを高速で非同期処理し、Form1で操作するユーザ様が重く感じないようにしたいです。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

今時でしたら、BackgroundWorkerを使うのではなくTaskを使用した方がよろしいかと思います。

フォームにボタン、ラベル、その他処理中に操作するコントロール(TextBoxなど)を置いてください。

VB.NET

1 Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 2 'もう一度押されないように無効化する 3 Button1.Enabled = False 4 5 '処理を開始 6 Dim task = Tasks.Task.Run(Sub() 7 'CSVを作成 8 CreateCSV() 9 'DBにInsert 10 InsertDB() 11 'DBをUpdate 12 UpdateDB() 13 End Sub) 14 15 '完了するまで待機 16 Await task 17 18 MessageBox.Show("完了しました") 19 20 'ボタンを再度有効化 21 Button1.Enabled = True 22 End Sub 23 24 25 Private Sub CreateCSV() 26 27 For i = 1 To 20000 28 Thread.Sleep(1) 29 Dim cnt As Integer = i 30 Me.Invoke(Sub() 31 Label1.Text = $"CSV作成中({cnt})" 32 End Sub) 33 Next 34 35 End Sub 36 37 Private Sub InsertDB() 38 39 For i = 1 To 20000 40 Thread.Sleep(1) 41 Dim cnt As Integer = i 42 Me.Invoke(Sub() 43 Label1.Text = $"DBにInsert中({cnt})" 44 End Sub) 45 Next 46 47 End Sub 48 49 Private Sub UpdateDB() 50 51 For i = 1 To 20000 52 Thread.Sleep(1) 53 Dim cnt As Integer = i 54 Me.Invoke(Sub() 55 Label1.Text = $"DBにUpdate中({cnt})" 56 End Sub) 57 Next 58 59 End Sub 60

ボタンを押したら処理が開始しますので、いろいろ画面を触ってみてください。

投稿2019/07/06 01:49

YAmaGNZ

総合スコア10251

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chintao1224

2019/07/06 02:08

不勉強でご迷惑をおかけします。CreateCSVの中にタイマー1は使えるのでしょうか?
YAmaGNZ

2019/07/06 02:16

タイマーで何を行っているのでしょうか? もしかして、行いたい処理というのは 一定間隔でCSVを作り、データベースへ反映する という処理でしょうか? もしそうだとすれば、提示したソースはボタンのクリックイベントで処理を開始していますが、タイマーイベントで行うようにすればいいだけだと思います。 また、CSV、Insert、Updateを別々のタイミングで処理したいというのであれば、別々のタイミングでTaskを生成すればいいかと思います。
chintao1224

2019/07/06 02:35

なるほどですね。ありがとうございます。基本的なことを質問させてください。タイマーイベントで処理するということは非同期で軽くなるということと同じことなのでしょうか?
YAmaGNZ

2019/07/06 03:16 編集

タイマーは非同期で処理を行うために使用するものではありません。 使うタイマーによっては非同期にもなりません。 どうもそのあたりが勘違いのもとになっているのだと思います。 例えば、 ・10分間隔で処理を行いたい  こういうことであれば、タイマーを使用するべきだと思います。 ・20000件のデータを処理したい  1件の処理時間が短いから、タイマーを100ms間隔くらいで動作させて  20000回行ったらタイマーを止めよう  こうすれば、UIも止まったように見えないから非同期に行ってるよね?  こういう考えは間違いだと思います。
guest

0

BackgroundWorkerというのがあるのを知り、使ってみようと思っているのですが。。。

今時何故 BackgroundWorker を使うのか分かりませんが(.NET 4.5 以降が使えない事情がある?)、それはちょっと置いといて・・・

どう使うべきか、どの方法が一番軽くなるか悩んでいます。
大量のデータを高速で非同期処理し、Form1で操作するユーザ様が重く感じないようにしたいです。

作ってるのは Windows Forms アプリですよね? 「どの方法が一番軽くなるか」とか「高速で」というところにに誤解がありそうな気がします。

マルチスレッドにすると高速で処理が終わるので軽くなると理解しているとするとそれは誤解です。処理時間は変わらりません。スレッドの取得・切り替えなのどオーバーヘッドで逆に遅くなることはありますが。

Windows Forms アプリでマルチスレッドにするのは UI 応答性の向上です。処理速度の向上ではありません。

例えば、以下のように 3 秒スリープするメソッドを同期で実行するのと非同期で実行する場合を考えます。

// テスト用の時間がかかるメソッド private string TimeCosumingMethod(string s) { if (string.IsNullOrEmpty(s)) { throw new ArgumentException("引数が無い"); } Thread.Sleep(3000); return s + " + ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId; }

実装例は以下の記事の通りです。

デリゲートを利用した非同期メソッドの実装
http://surferonwww.info/BlogEngine/post/2019/06/19/coding-asynchronous-method-by-using-delegate-in-windows-forms-application.aspx

同期呼び出し(button1 クリック)するとフォームは 3 秒フリーズしてユーザーの操作(フォームのドラッグなど)を受け付けなくなります。

非同期呼び出し(button2 または button3 クリック)すると、上の「テスト用の時間がかかるメソッド」は、呼び出し元のスレッド(上の記事の画像で ManagedThreadId: 1)とは別のスレッド(ManagedThreadId: 3)で動きます。OS が自動的に高速でスレッドを切り替えながら実行するので呼び出し元のフォームへのユーザーの操作は処理され、フリーズすることはありません。

でも、3 秒スリープするのは同じことで、それが短縮されることはありません。

投稿2019/07/06 03:11

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chintao1224

2019/07/07 11:37

勉強になりました。ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/07/07 12:55

非同期にする意味理解できているでしょうか? 大丈夫ですかね? 何となくわかってないような気がしますけど。
guest

0

今どきBackgroundWorkerを積極的に使うのもどうかと思うので、回答そのものは他に挙がっているとおりasync/await(Task)を使うべきだと思います。

ちょと気になるのが

大量のデータを高速で非同期処理し、Form1で操作するユーザ様が重く感じないようにしたいです。

非同期処理は「高速化」のために使われるものではありません。
処理中に他の作業(主にUIの操作)が行えるようにするものです。
処理そのものが早くなるわけではないです。

また、タイマー云々というのがイマイチよくわかりません。何の目的で使うのでしょうか?

投稿2019/07/06 03:01

gentaro

総合スコア8949

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問