tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルBackgroundoworker
記事No11193
投稿日: 2013/12/24(Tue) 17:43
投稿者スレッド
VBでbackgroundworkerコントロールをはりつけ時間がかかる処理をスレッドで実行しようと考えています。
vb画面でボタンを押した時に backgroundWorker1.RunWorker.Async()を呼び出す。

BackgroundWorker1_DoWorks の中で
DatagridView.Rows.Add でデータを追加したいのですが例外で落ちてしまいます。
Invokeしていないのが原因かと考えてますがロジックの
実装方法がよくわかりません。

どなたかご教授いただければ幸いです。
宜しくお願いします。

[ツリー表示へ]
タイトルRe: Backgroundoworker
記事No11194
投稿日: 2013/12/24(Tue) 22:34
投稿者魔界の仮面弁士
> backgroundWorker1.RunWorker.Async()を呼び出す。
  backgroundWorker1.RunWorkerAsync() ですよね?

> BackgroundWorker1_DoWorks の中で
  BackgroundWorker1_DoWork ですよね?


> DatagridView.Rows.Add でデータを追加したいのですが例外で落ちてしまいます。
他スレッドで管理されている変数に手を出してはいけません。
対応策としては、たとえばこんな感じ。

Imports System.ComponentModel

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        BackgroundWorker1.WorkerReportsProgress = True
        DataGridView1.ColumnCount = 3
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.ReadOnly = True
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        DataGridView1.Rows.Clear()
        BackgroundWorker1.RunWorkerAsync(1000)
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim bgw = DirectCast(sender, BackgroundWorker)
        Dim count = CInt(e.Argument)

        For I = 1 To count
            Dim data(2) As Object
            data(0) = CStr(I) & "-1"
            data(1) = CStr(I) & "-2"
            data(2) = CStr(I) & "-3"

            System.Threading.Thread.Sleep(15)

            '直接DataGridViewを操作するのではなく、
            'データのコピーのみを渡すようにする
            bgw.ReportProgress(0, data.Clone())
        Next
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        'ProgressChanged イベントは、呼び出し元のスレッドで
        '発生するので、ここで、受け取ったデータを画面に表示する
        Dim data() As Object = DirectCast(e.UserState, Object())
        DataGridView1.Rows.Add(data)
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        If BackgroundWorker1.IsBusy Then
            e.Cancel = True
            MsgBox("現在処理中です")
        End If
    End Sub

End Class

[ツリー表示へ]