tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルForm_Loadイベント
記事No6676
投稿日: 2007/12/14(Fri) 18:48
投稿者ゆうき
ゆうきです。いつもお世話になっています。

Form_Loadイベントに処理を書いて実行すると、
処理を終えてからフォームが表示されてしまいます。

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '処理(例)
    Label1.Text = ""
    End Sub

この処理例にすると、最初のラベルのテキストが表示される前に
(フォームが表示される前に)ラベルのテキストが書き換わって
フォームが表示されます。他にもいろいろ調べましたが、わかりません。

どうすればよいのでしょう。よろしくお願いします。

[ツリー表示へ]
タイトルRe: Form_Loadイベント
記事No6677
投稿日: 2007/12/14(Fri) 19:02
投稿者魔界の仮面弁士
> Form_Loadイベントに処理を書いて実行すると、
> 処理を終えてからフォームが表示されてしまいます。

表示後に処理したいなら、Load ではなく Shown に書くとか、
あるいは、処理の実行を呼び出し元に任せる、とか。

[ツリー表示へ]
タイトルRe^2: Form_Loadイベント
記事No6678
投稿日: 2007/12/14(Fri) 19:35
投稿者ゆうき
魔界の仮面弁士さん、回答ありがとうございます。

> 表示後に処理したいなら、Load ではなく Shown に書くとか、
Shownイベントを試しましたが、コントロールが真っ白になって
直ったころには処理が終わっていました。

もっと適切なイベントはないのでしょうか。
ないなら、他に方法はないのでしょうか。

ご指導よろしくお願いします。

[ツリー表示へ]
タイトルRe^3: Form_Loadイベント
記事No6679
投稿日: 2007/12/14(Fri) 19:50
投稿者魔界の仮面弁士
> > 表示後に処理したいなら、Load ではなく Shown に書くとか、
> Shownイベントを試しましたが、コントロールが真っ白になって
> 直ったころには処理が終わっていました。

時間がかかる処理に対しては、BackgroundWorker を使ってみてください。
たとえば、

 Private Sub Form1_Shown(……
  '時間のかかる処理
  System.Threading.Thread.Sleep(3000) '3秒待機
  Me.Label1.Text = "終わり!"
 End Sub

のようなコードだと、最初の 3 秒間、ラベルが 真っ白になってしまいますが、
下記のように、BackgroundWorker を併用すれば、それを回避できます。

 Public Class Form1
  Private Sub Form1_Shown(……
   Me.BackgroundWorker1.RunWorkerAsync("任意の引数")
  End Sub

  Private Sub BackgroundWorker1_DoWork(……
   '引数を受け取る
   Dim arg As Object = e.Argument

   'ここに時間のかかる処理を記述
   System.Threading.Thread.Sleep(3000) '3秒待機

   '結果を返す
   e.Result = "終わり!"
  End Sub

  Private Sub BackgroundWorker1_RunWorkerCompleted(……
   '結果を受け取る
   Dim ret As Object = e.Result

   Me.Label1.Text = CStr(ret)
  End Sub
 End Class

[ツリー表示へ]
タイトルRe^4: Form_Loadイベント
記事No6680
投稿日: 2007/12/15(Sat) 07:00
投稿者ゆうき
ゆうきです。
魔界の仮面弁士さん、回答ありがとうございます。

>   Private Sub BackgroundWorker1_DoWork(……
>    '引数を受け取る
>    Dim arg As Object = e.Argument
>
>    'ここに時間のかかる処理を記述
>    System.Threading.Thread.Sleep(3000) '3秒待機
>
>    '結果を返す
>    e.Result = "終わり!"
>   End Sub
やってみましたが、上記のコード内でLabelのTextプロパティを設定すると
例外が発生して
有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'Label1' がアクセスされました。
といわれてしまいます。

どういうことかわからないので
また書き込みました。よろしくお願いします。

[ツリー表示へ]
タイトルRe^5: Form_Loadイベント
記事No6681
投稿日: 2007/12/15(Sat) 09:16
投稿者魔界の仮面弁士
> やってみましたが、上記のコード内でLabelのTextプロパティを設定すると

DoWork(ワーカースレッド)から、フォームやコントロールといった
メインスレッドのオブジェクトを操作する事はできません。

# コントロールだけでなく、たとえば Private a As Integer のような、
# 単純な変数の読み書きさえ、基本的には NG です。
## 変数を排他ロックしたり、System.Threading.Interlocked にて
## 読み書きするならば安全ですが。

非同期処理の途中経過を表示したい場合は、ReportProgress メソッドを用います。


Public Class Form1
 Private Sub Form1_Load(……
  '進捗確認を行えるようにしておく。
  Me.BackgroundWorker1.WorkerReportsProgress = True

  'ついでに、キャンセルも行えるようにしてみる。
  Me.BackgroundWorker1.WorkerSupportsCancellation = True
  Me.Button1.Text = "キャンセル"

  '処理開始
  Me.BackgroundWorker1.RunWorkerAsync()
 End Sub

 '★ 途中経過を受け取るためのイベント ★
 Private Sub BackgroundWorker1_ProgressChanged(……
  '状況がイベントとして通知されるので、
  'ProgressPercentage (進捗のパーセンテージ)か
  'UserState (状況を表す任意のデータ)を受け取り、表示する。
  Me.Label1.Text = CStr(e.UserState)
 End Sub

 Private Sub Button1_Click(……
  Me.Button1.Enabled = False
  'キャンセル処理をさせたい時には、このメソッド。
  Me.BackgroundWorker1.CancelAsync()
 End Sub

 Private Sub BackgroundWorker1_DoWork(……
  Dim bgw As System.ComponentModel.BackgroundWorker
  bgw = DirectCast(sender, System.ComponentModel.BackgroundWorker)

  For n As Integer = 0 To 100
   '進捗報告
   Dim state As Object = "現在" & CStr(n) & "%です。"
   bgw.ReportProgress(n, state) '★ 途中経過を報告するためのメソッド ★

   '時間のかかる処理
   System.Threading.Thread.Sleep(100) '0.1秒待機

   'キャンセルが要求されたか?
   If bgw.CancellationPending Then
    e.Cancel = True
    Return
   End If
  Next

  e.Result = "結果"
 End Sub

 Private Sub BackgroundWorker1_RunWorkerCompleted1(……
  '結果表示
  If e.Error IsNot Nothing Then
   Me.Label2.Text = "処理中にエラー発生:" & e.Error.Message
  ElseIf e.Cancelled Then
   Me.Label2.Text = "ユーザー操作によってキャンセルされました。"
  Else
   Me.Label2.Text = CStr(e.Result)
  End If
 End Sub
End Class

[ツリー表示へ]
タイトルRe^6: Form_Loadイベント
記事No6682
投稿日: 2007/12/15(Sat) 10:27
投稿者ゆうき
回答ありがとうございます。

魔界の仮面弁士さんのおかげで
処理を書くことができました。
ありがとうございます。

これからもよろしくお願いします。

[ツリー表示へ]