投稿者 パル36  (中学生) 投稿日時 2011/10/15 11:29:19
こんにちは。毎回お世話になっています。

今回は、ダウンロードを非同期化させたいと思ってプログラムしたのですが、
うまくいきません。

解決策を教えていただけないでしょうか。

↓元のコード
        Try
            Dim NumCount As Integer = 0 '連番ファイルカウント 
            lbl.Text = "状況 : ダウンロードを開始します..."

            If MsgBox( "ダウンロードを開始しますか。", MsgBoxStyle.YesNo Or MsgBoxStyle.Question, "ダウンロードを開始しようとしています。") = MsgBoxResult.Yes Then
                My.Computer.Audio.PlaySystemSound(System.Media.SystemSounds.Question)
                For Each checked As String In List1.CheckedItems
                    Dim wc As New WebClient 'インスタンス 
                    Dim SavePath As String = My.Application.Info.DirectoryPath '保存先 
                    Dim Ext As String = Path.GetExtension(checked) 'URLから拡張子だけを取得 

                        '保存ファイル名を連番にする 
                        My.Computer.Network.DownloadFile(New Uri(checked), Path.Combine(SavePath, "Image" & NumCount & Ext), """"True, 30000, True, FileIO.UICancelOption.ThrowException)
                        NumCount = NumCount + 1

                    wc.Dispose()
                Next
            Else
                lbl.Text = "状況 : ダウンロードを中止しました。"
                Exit Sub
            End If
            lbl.Text = "状況 : ダウンロードが完了しました。"

        Catch ex As Exception
            lbl.Text = ex.Message
            txtLog.Text += vbCrLf & "・エラーが発生しました。" & vbCrLf & "エラーメッセージ:" & ex.Message & "スタックトレース:" & ex.StackTrace
            TabControl.SelectTab(1)
            txtLog.Select(0, 0)
        End Try
    End Sub


New Uri(checked)は、下のコードでブラウザから画像URLを取得し、
リストボックスに表示させているアイテムです。

        List1.Items.Clear()
        List2.Items.Clear()
        Dim Body As HtmlElement = BrowserMain.Document.Body
        Dim Images As HtmlElementCollection = Body.GetElementsByTagName("img")
        For Each Img As HtmlElement In Images
            Dim src As String = Img.GetAttribute("src")
            Dim ext As String = Path.GetExtension(src)
            List1.Items.Add(src)
            If Not List2.Items.Contains(ext) Then
                List2.Items.Add(ext, True)
            End If
        Next


上記は動きますが、たくさんチェックされているとダウンロードの間、なにもできません。

なので、http://www.vbstation.net/tips/downloadfileasync.htm
を参照してやってみました。

しかし、複数チェックしてダウンロードすると

エラーメッセージ:WebClient は同時 I/O 操作をサポートしません。
スタックトレース:場所 System.Net.WebClient.ClearWebClientState()
   場所 System.Net.WebClient.DownloadFileAsync(Uri address, String fileName, Object userToken)
   場所 System.Net.WebClient.DownloadFileAsync(Uri address, String fileName)

とエラーが出てしまいます。
Disposeの位置を変えても変わりませんでした。また、インスタンスのスコープを変えて見ましたが変わりませんでした。

失敗したコードを載せます。

For Each checked As String In List1.CheckedItems
                    Dim WebDownload As New WebClient 'インスタンス 
                    Dim SavePath As String=My.Application.Info.DirectoryPath '保存先 
                    Dim Ext As String = Path.GetExtension(checked) 'URLから拡張子だけを取得 
                    Dim URL As System.Uri = New Uri(checked)

                        '保存ファイル名を連番にする 
                        _Download.DownloadFileAsync(URL, Path.Combine(SavePath, "Image" & NumCount & Ext))
                        NumCount = NumCount + 1

                    End If
                    WebDownload.Dispose()
                Next

            End If


My.Computer.Network.DownloadFileではできたのに、DownloadFileAsyncではこのようなことはできないのでしょうか。
同時ダウンロードではなく、1つが完了したら次をダウンロードしたいです。

タイマーを使って、数秒後に確認しダウンロード中だったら待機させようとしましたができませんでした。
(どうすればいいかわかりませんでした。)

自分では解決策が見つかりませんでした。
スレッドを別にしたりしないといけないのでしょうか。

よろしくお願いします。
なにかコードが不明な箇所があればいってください。(一部書き換えたので)