- PR -

WebBrowser コントロールを非同期で操作したい。

投稿者投稿内容
しん
常連さん
会議室デビュー日: 2004/10/08
投稿数: 20
投稿日時: 2008-12-26 03:47
コメント有難うございます。

渋木宏明(ひどり) 様、unibon 様

教えて頂いたことを私なりに精一杯学び、以下のような結果を得ることができました。

Thread クラスを用いて、STA 指定してスタートすることで
別スレッド内で WebBrowser オブジェクトのインスタンスを生成し、
Navigate 等の操作を行うことができました。
また、フォーム上に配置したコントロールへのアクセスを
Invoke で行うことができました。
有難うございました。

フォーム上に配置した WebBrowser に対してフォームロード時に
.Navigateメソッドを実行するとフォームの表示が極端に遅くなってしまうのは
相変わらずです。ご教授頂いた Form_Activated 、Form_Shown での処理を
試してみたいと思います。ご教授有難うございました。
私の環境は、Windows XP / IE 6.0 / Visual Basic 2005 / .NET Framework 2.0
です。憶測でしかありませんが、.NET Framework 3.5 はスレッド処理について
強化されているのか、単に私のパソコンの処理能力が低いだけの可能性もあります。


また、別スレッドでの処理結果を取得したいと思い、
BeginInvoke、EndInvoke について調べ、簡単な計算処理を
別スレッドで行い、その結果を取得することはできました。
ただ、BeginInvoke で開始するスレッドに対して、STA 指定する方法がわからず
WebBrowser を扱うことはできない状態です。
根本的な概念をわかっていないだけかもしれず、申し訳ありません。
BeginInvoke で開始するスレッドに対して STA 指定をする方法は
ないのでしょうか。

Form_Load をコンストラクタと表現してしまい、失礼致しました。
Sub New() と Form_Load をごっちゃにしてしまうような
不適切な表現をしてしまい、恥ずかしい限りです。以後気をつけます。

また、私の無茶な相談内容についてご回答頂き感謝しております。
有難うございます。m(。_。)m
しん
常連さん
会議室デビュー日: 2004/10/08
投稿数: 20
投稿日時: 2008-12-29 08:26
別スレッド上で WebBrowser オブジェクトの作成及び
ナビゲート操作、表示を行うことができました。

以下のコードにはまだ課題(※)がありますが、
質問のタイトル内容から外れてしまうため、
今回はこれにて解決としたいと思います。

○フォーム Form1 上に以下のコントロールを配置。
・Button1 …処理開始ボタン
・TextBox1 …URL 入力用
・Panel1 …別スレッドで作成した WebBrowser を配置するためのスペース(未使用)

○コード
コード:

Imports System.Threading

' 別スレッドで WebBrowser を操作する。
Public Class Form1

' Me.Button1 をクリックした時
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Me.Button1.Enabled = False

Dim t As New Thread(AddressOf DoWork)
' STA を指定
t.SetApartmentState(ApartmentState.STA)
t.IsBackground = True
t.Start(Me.TextBox1.Text)

End Sub

' Me.Button1 クリック時に開始されるスレッド
Sub DoWork(ByVal url As Object)

Dim wb As New WebBrowser
wb.Name = "wb" 'エラー発生時の識別用
wb.Navigate(url)

' 読み込み待ち
' ループを用いて、読み込みが完了するまで待つ。
' wb.DocumentCompleted イベントハンドラは使用せず。
' 使用したとしても、読み込み完了まで当メソッドを抜けてはいけない。
' 当メソッドを抜けると、wb.DocumentCompleted イベントが発生しない。
' スレッドが終了してしまうため、wb.Navigate(url) の処理が完了しない
' ままになってしまう?(不明)

While wb.IsBusy

' 読み込み待ち
Application.DoEvents() ' 当スレッド内の他の処理を進めるために必要

End While

Do Until wb.ReadyState = WebBrowserReadyState.Complete

' 読み込み待ち
Application.DoEvents() ' 当スレッド内の他の処理を進めるために必要

Loop

MessageBox.Show("ナビゲート完了")

' フォームを作成して WebBrowser オブジェクト wb を表示
Dim f As New Form
f.Controls.Add(wb)
f.ShowDialog()
f.Dispose()

Me.Button1.Enabled = True

'【A】

End Sub

'【B】

End Class




※今後の課題
 別スレッドで作成した WebBrowser オブジェクトをメインスレッドに渡したい。
(上記コードの DoWork メソッド内で作成した wb をメインフォームに貼り付けたい。)
上記コードの DoWork メソッド最後の 【A】 の部分に以下のようなコードを追加し、
【B】 の部分に以下のようなデリゲート及びメソッドを追加したところ、
エラーが発生。エラー内容は、コメント文参照。

コード:

'【A】に追加したコード

'メインフォーム Form1 に wb を追加する。

'setWeb(wb) '←setWeb 内でエラー(※2)

Dim dlgt As New setWebDelegate(AddressOf setWeb)

'Me.Invoke(dlgt, wb) '←エラー(※2)

'wb.Invoke(dlgt, wb) '←エラー(※2)



引用:

※2 エラー内容
「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'wb' がアクセスされました。」



コード:

'【B】に追加したコード

Delegate Sub setWebDelegate(Byval wb As WebBrowser)

'メインフォームに wb コントロールをセットする。
Sub setWeb(Byval wb As WebBrowser)

If Me.InvokeRequired Then
'別スレッドによって呼ばれた場合

'メインスレッドに Invoke する。
Me.Invoke(New setWebDelegate(AddressOf setWeb), wb)
Exit Sub
End If

'以下の処理は必ずメインフォームを作成したスレッドで実行される。
'Synclock 等が必要?
Me.Panel1.Controls.Add(wb)

End Sub




[ メッセージ編集済み 編集者: しん 編集日時 2008-12-29 09:57 ]
アウ
ベテラン
会議室デビュー日: 2008/12/18
投稿数: 72
投稿日時: 2008-12-29 16:00
(利用規約違反のため削除いたしました。@ITクラブメンバーシップセンター)
アウ
ベテラン
会議室デビュー日: 2008/12/18
投稿数: 72
投稿日時: 2008-12-29 16:01
(利用規約違反のため削除いたしました。@ITクラブメンバーシップセンター)
アウ
ベテラン
会議室デビュー日: 2008/12/18
投稿数: 72
投稿日時: 2009-01-03 12:55
(利用規約違反のため削除いたしました。@ITクラブメンバーシップセンター)

スキルアップ/キャリアアップ(JOB@IT)