投稿者 YuO  (社会人) 投稿日時 2011/10/17 16:15:01
> >ただし,UIへのアクセスができないので,その部分を考えて処理する必要があります。
> そのアクセスというのはどういうものなのでしょうか。

基本的に,UIに対して「データの取得」「データの設定」といった行為は,全部できないと考えてください。
例えば,
> For Each checked As String In List1.CheckedItems
は,List1.CheckedItems.GetEnumerator()という「UIデータの取得行為」を行っているので,例外が発生します。
もちろん,MessageBoxもだめですし,ラベルへのTextの設定もだめです。

取得に関しては先に取得しておき,設定や表示に関してはReportProgressイベントやRunWorkerCompletedイベントで行います。

    Private Sub button1_Click (sender As Object, e As EventArgs) Handles button.Click
       ' ボタンのハンドラ = UIスレッド 
       button1.Enabled = False
       lbl.Text = "状況 : ダウンロードを開始します..."
       If MsgBox( "ダウンロードを開始しますか。", MsgBoxStyle.YesNo Or MsgBoxStyle.Question, "ダウンロードを開始しようとしています。") <> MsgBoxResult.Yes Then
           lbl.Text = "状況 : ダウンロードを中止しました。"
           button1.Enabled = True
           Return
       End If

       My.Computer.Audio.PlaySystemSound(System.Media.SystemSounds.Question)
       backgroundWorker1.RunWorkerAsync(List1.CheckedItems.Cast(Of String)().ToArray()) ' LINQ使ってCheckedItemsをString()に変換して渡す 
    End Sub

    Private Sub backgroundWorker1_DoWork (sender As Object, e As DoWorkEventArgs) Handles backgroundWorker1.DoWork
       ' DoWorkイベント = バックグラウンドスレッド 
        Dim checkedItems As String() = DirectCast(e.Argument, String())
        Dim numCount As Integer = 0 '連番ファイルカウント  

        Using (wc As New WebClient())
            For Each checked As String In checkedItems
                Dim savePath As String = My.Application.Info.DirectoryPath '保存先  
                Dim saveFileName = Path.Combine(savePath, "Image" & numCount & Path.GetExtension(checked))

                ' 同期ダウンロード 
                wc.DownloadFile(checked, saveFileName)
                numCount += 1
            Next
        End Using
    End sub

    Private Sub backgroundWorker1_RunWorkerCompleted (sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker.RunWorkerCompleted
       ' 終了ハンドラ = UIスレッド 
        If e.Error IsNot Nothing Then
             lbl.Text = e.Error.Message
             txtLog.Text &= vbCrLf & "・エラーが発生しました。" & vbCrLf & "エラーメッセージ:" & e.Error.Message & "スタックトレース:" & e.Error.StackTrace
             TabControl.SelectTab(1)
             txtLog.Select(0, 0)
        Else
             lbl.Text = "状況 : ダウンロードが完了しました。"
        End If
       button1.Enabled = True
    End Sub



個人的には,
Blog: マルチスレッド Windows フォームアプリケーションの開発 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
http://blogs.msdn.com/b/nakama/archive/2009/03/30/windows.aspx
の,一連の記事を読むとよいと思っています (コードはC#で書かれていますが)。
最低でも,
Blog: Part 4. Visual Studio によるマルチスレッドアプリの開発 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
http://blogs.msdn.com/b/nakama/archive/2009/04/09/part-4-visual-studio.aspx
にはBackgroundWorkerについて色々書いてあるので読むべきです。
# 日本マイクロソフトの赤間さんの記事です。