Simon said:
I think I'm doing this wrong :
I have a class with a public shared method such as follows:
public shared sub myFunction
dim frm as new myFrm
dim t as new Threading.Thread(Addressof myFrm.myShowDialog
t.start
end sub
In the frm - the myShowDialog just does a "me.showdialog".
The idea is that this function will display a form, but then return control
back to the calling routine immediately without waiting for the form to be
closed.
It works, but I've had several reports of the form that is displayed
"crashing" as it is being displayed, with random errors (I've not got a
sample) or the whole application just disappearing (without error).
Can anybody assist, either by confirming or otherwise that what I'm doing is
reasonable, or perhaps letting me know a better way.
Simon...
All of this really depends on your architecture. Is this routine that
is showing the form on a background thread? If it is, that would
explain why the form exits when the routine ends. If it is on a
background thread, there is no message pump and the form will exit when
the routine ends because the thread exits.
Here is three different methods of showing a form:
Option Strict On
Option Explicit On
Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents Button3 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.Button3 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(0, 0)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(328, 23)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Show Form On Current Thread (Form.Show)"
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(0, 28)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(328, 23)
Me.Button2.TabIndex = 1
Me.Button2.Text = "Show Form On New Thread (Application.Run)"
'
'Button3
'
Me.Button3.Location = New System.Drawing.Point(0, 56)
Me.Button3.Name = "Button3"
Me.Button3.Size = New System.Drawing.Size(328, 23)
Me.Button3.TabIndex = 2
Me.Button3.Text = "Show Form On New Thread (ShowDialog)"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(328, 82)
Me.Controls.Add(Me.Button3)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
<DllImport("kernel32")> _
Public Shared Function GetCurrentThreadId() As IntPtr
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim frm As New Form2
frm.Show()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Dim thrd As New Thread(AddressOf ShowFormAppRun)
thrd.ApartmentState = ApartmentState.STA
thrd.Start()
End Sub
Private Sub ShowFormAppRun()
Dim frm As New Form2
Application.Run(frm)
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim thrd As New Thread(AddressOf ShowFormDialog)
thrd.ApartmentState = ApartmentState.STA
thrd.Start()
End Sub
Private Sub ShowFormDialog()
Dim frm As New Form2
frm.ShowDialog()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Text = String.Format("Main Form - Thread ID {0}",
Form1.GetCurrentThreadId())
End Sub
End Class
Public Class Form2
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
'
'Form2
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 30)
Me.Name = "Form2"
Me.Text = "Form2"
End Sub
#End Region
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Text = String.Format("Child Form - Thread ID {0}",
Form1.GetCurrentThreadId())
End Sub
End Class
There are two forms here, so look out if you copy paste the code. If
you don't find this stuff usefull, maybe you can post some code that
demonstrates more of your problem...