- TASU
- 会議室デビュー日: 2006/08/04
- 投稿数: 7
|
投稿日時: 2006-08-04 20:06
サブスレッドよりイベントを発生させ、非同期でフォームを表示させたいのですが、うまいこと動きません。
何かよい方法をご存知の方いらっしゃいましたら、教えていただきたいです。
よろしくお願いします。
一応、デリゲートを定義しBeginInvokeメソッドを使ってsbCls_FormShowを呼んだりしてみましたが、やり方が悪かったのかうまくいきませんでした。
(BeginInvokeメソッドを使うと、sbCls_FormShowが新規スレッド上で呼ばれるからでしょうか?方法がわかりませんが、sbCls_FormShowをメインスレッド上で呼べばうまくいきますでしょうか。)
↓サンプルソースです↓
(下記モジュール、クラスの他に空のフォームを2つ作成し、Form1にDialogResultプロパティ='OK'のボタンを追加してください。)
コード: |
|
Imports System.Threading
'==============================================================================
'==============================================================================
Module Main
Sub main()
Application.Run(New MainClass)
End Sub
End Module 'Main
'==============================================================================
'==============================================================================
Public Class MainClass
Inherits ApplicationContext
Friend WithEvents sbCls As SubClass
Friend WithEvents ntIcn As NotifyIcon
Friend WithEvents ctMnu As ContextMenu
Private IDX_END As Integer
Private IDX_SND As Integer
'サブスレッドより呼ばれるイベント
Private Sub sbCls_FormShow(ByVal str As String) Handles sbCls.FormShow
Dim f1 As New Form1
'このイベントを非同期で発生させるか、もしくは非同期でForm1を表示させたい
If f1.ShowDialog = DialogResult.OK Then
Dim f2 As New Form2
f2.Show()
End If
End Sub
Private Sub Menu_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ActMenu As MenuItem
ActMenu = CType(sender, MenuItem)
Select Case ActMenu.Index
Case IDX_END
sbCls.Dispose()
ntIcn.Dispose()
ExitThread()
Case IDX_SND
Dim f2 As New Form2
f2.Show()
End Select
End Sub
Public Sub New()
Thread.CurrentThread.Name = "MainThread"
'サブスレッドを開始するオブジェクト
sbCls = New SubClass
'----------------------------------'
'-----------メニュー定義-----------'
'----------------------------------'
Dim tmpMenu As MenuItem
ntIcn = New NotifyIcon
With ntIcn
.Icon = New System.Drawing.Icon("Icon1.ico")
.Visible = True
.Text = "MainClass"
End With
ctMnu = New ContextMenu
tmpMenu = New MenuItem("終了(&E)", New System.EventHandler(AddressOf Me.Menu_Click))
ctMnu.MenuItems.Add(tmpMenu)
IDX_END = tmpMenu.Index
tmpMenu = New MenuItem("表示(&V)", New System.EventHandler(AddressOf Me.Menu_Click))
ctMnu.MenuItems.Add(tmpMenu)
IDX_SND = tmpMenu.Index
ntIcn.ContextMenu = ctMnu
'----------------------------------'
'----------------------------------'
End Sub
End Class 'MainClass
'==============================================================================
'==============================================================================
Public Class SubClass
Implements IDisposable
Public Event FormShow(ByVal str As String)
Private t As Thread
'サブスレッド
Sub FormShowThread()
While True
RaiseEvent FormShow("aiu")
Thread.Sleep(10000)
End While
End Sub
Public Sub New()
'サブスレッドを開始する
t = New Thread(AddressOf FormShowThread)
With t
.IsBackground = False
.Name = "SubThread"
.Start()
End With
End Sub
Public Sub Dispose() Implements System.IDisposable.Dispose
t.Abort()
t.Join()
End Sub
End Class 'SubClass
|
|
- かずくん
- ぬし
- 会議室デビュー日: 2003/01/08
- 投稿数: 759
- お住まい・勤務地: 太陽系第三惑星
|
投稿日時: 2006-08-04 20:53
で?一番大事な、サブスレッドの実装はどうなってんの?
そこんとこ見せてもらわないと、回答しようが無いんじゃないの?
|
- よこけん
- 大ベテラン
- 会議室デビュー日: 2006/01/31
- 投稿数: 216
|
投稿日時: 2006-08-04 21:04
何がしたいのか、どこが問題なのかがいまいちよくわかりません。
Form1を閉じると、すぐさまForm2が開き、その10秒後に再びForm1が開かれるようにしたいが、
なぜかForm2をクリックしても応答無しとなってしまうことが問題ということですか?
それとも、全く違う動作をさせたいのに上記のような意味不明な動作をしてしまうのが問題ですか?
|
- TASU
- 会議室デビュー日: 2006/08/04
- 投稿数: 7
|
投稿日時: 2006-08-05 16:16
かずくんさん、けんじさん早速の返信有難うございます。問題点があまりにも不明確でしたね。申し訳ありません。
Thread.Sleep(10000)で実際にはUdpClientクラスのReceiveメソッドを使って受信待機させてます。データ受信時にForm1にデータ内容を表示させ、Form1を閉じるとForm2を表示させ返信できる処理、つまるところはメッセンジャーを作りたいです。(メッセンジャーが欲しい訳ではなくて、勉強のつもりでつくり始めました。)
が、けんじさんからの質問にもありましたとおり、Form2が動かなくなってしまいます。
自分の勉強不足ですが、原因がわかりません。
ちんぷんかんぷんな質問ばかりで申し訳ありませんが、お答えいただけると助かります。
よろしくお願いします。
|
- よこけん
- 大ベテラン
- 会議室デビュー日: 2006/01/31
- 投稿数: 216
|
投稿日時: 2006-08-05 18:25
Form2を呼び出す処理も更に別スレッドで行うようにしてください。
その際、Form2はShowDialogで呼び出してください。
|
- TASU
- 会議室デビュー日: 2006/08/04
- 投稿数: 7
|
投稿日時: 2006-08-07 18:53
けんじさん返信有難うございます。
教えていただいた、
引用: |
|
Form2を呼び出す処理も更に別スレッドで行うようにしてください。
その際、Form2はShowDialogで呼び出してください。
|
で、うまく動作しました。 ・・・が、
実は、Form2をインスタンス化するときに引数を渡しており、それを実現させるために、
引数を渡せるようにデリゲート宣言をし、BeginInvokeメソッドを使ってみました。
するとForm2のコマンドボタン押下時にフォルダブラウザを表示させているのですが、
それが正しく(枠のみでツリー部が)表示されません。
理由が全く解りません。ご存知の方いらっしゃいましたら、教えていただきたいです。
よろしくお願いします。
↓上記ソースのForm2をForm1とし、簡略化したサンプルです↓
Imports System.Threading
コード: |
|
'==============================================================================
'==============================================================================
Module Main
Sub main()
Application.Run(New MainClass)
End Sub
End Module 'Main
'==============================================================================
'==============================================================================
Public Class MainClass
Inherits ApplicationContext
Friend WithEvents ntIcn As NotifyIcon
Friend WithEvents ctMnu As ContextMenu
Public Delegate Sub Form1Delegate()
Private IDX_END As Integer
Private IDX_SND As Integer
Private Sub RunForm1Thread()
'デリゲート定義 - Form1でフォルダブラウザのフォルダツリーが
表示されない!
Dim dlgt As Form1Delegate = New Form1Delegate(AddressOf Form1Thread)
dlgt.BeginInvoke(Nothing, Nothing)
'スレッド定義 - Form1でフォルダブラウザのフォルダツリーが
正しく表示される
'Dim thrd As Thread = New Thread(AddressOf Form1Thread)
'thrd.Start()
End Sub
Sub Form1Thread()
Dim f1 As New Form1
f1.ShowDialog()
End Sub
Private Sub Menu_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ActMenu As MenuItem
ActMenu = CType(sender, MenuItem)
Select Case ActMenu.Index
Case IDX_END
ntIcn.Dispose()
ExitThread()
Case IDX_SND
RunForm1Thread()
End Select
End Sub
Public Sub New()
'----------------------------------'
'-----------メニュー定義-----------'
'----------------------------------'
Dim tmpMenu As MenuItem
ntIcn = New NotifyIcon
With ntIcn
.Icon = New System.Drawing.Icon("Icon1.ico")
.Visible = True
.Text = "MainClass"
End With
ctMnu = New ContextMenu
tmpMenu = New MenuItem("終了(&E)", New System.EventHandler(AddressOf Me.Menu_Click))
ctMnu.MenuItems.Add(tmpMenu)
IDX_END = tmpMenu.Index
tmpMenu = New MenuItem("表示(&V)", New System.EventHandler(AddressOf Me.Menu_Click))
ctMnu.MenuItems.Add(tmpMenu)
IDX_SND = tmpMenu.Index
ntIcn.ContextMenu = ctMnu
'----------------------------------'
'----------------------------------'
End Sub
End Class 'MainClass
'==============================================================================
'==============================================================================
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows フォーム デザイナで生成されたコード "
〜 中略 〜
#End Region
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim FolderBrowser As New FolderBrowserDialog
If FolderBrowser.ShowDialog = DialogResult.OK Then
End If
FolderBrowser.Dispose()
End Sub
End Class
|
|
- TASU
- 会議室デビュー日: 2006/08/04
- 投稿数: 7
|
投稿日時: 2006-08-10 11:11
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
・・・いまだにわかりません。
どなたか解答してやってください。
お願いします。
|
- Hongliang
- ぬし
- 会議室デビュー日: 2004/12/25
- 投稿数: 576
|
投稿日時: 2006-08-10 12:10
スレッドアパートメントの問題でしょう。
……が、そもそもなぜ別スレッドでウィンドウを開けなければならないのか良く分からない……。
GUI スレッドは一つでいいと思うんですけどねー。
|