Home All Groups Group Topic Archive Search About
Author
10 Aug 2006 10:57 PM
Aaron
Hi,

1.  Can a seperate thread create a form?

I created some test code.  I have a sub Test that attempts to create
and show a form, objFrmTest which is of type frmTest.   Button1 and
Button2 exist on another form (not frmTest). Button1 attempts to run
sub Test with another thread, which Button2 simply attempts to run sub
Test.  The results, in short, are the Button1 does not work while
Button2 does.  Also, once Button1 is run, neither will work properly
there after.

I setup some breakpoints and did found that in both cases, the creating
thread sucessfully ran both the form constructor and the Load event.
In spite of that though, Button1 cannot bring up frmTest.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
        Dim thdTest As Thread
        thdTest = New Thread(AddressOf Test)
        thdTest.Name = "ThreadTest"
        thdTest.Priority = ThreadPriority.Highest
        thdTest.Start()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
        Test()
    End Sub

    Public Sub Test()
        If objFrmDiscrepancy Is Nothing Then
            objFrmDiscrepancy = New frmDiscrepancy
        ElseIf objFrmDiscrepancy.IsDisposed Then
            objFrmDiscrepancy = Nothing
            objFrmDiscrepancy = New frmDiscrepancy
        End If

        objFrmDiscrepancy.Show()
        objFrmDiscrepancy.WindowState = FormWindowState.Normal
    End Sub

2.  Assuming that a thread can create a form, will all the event
handlers on the form execute against the primary thread (default
thread? application thread?) or the thread that created it?

3.  Can a form be configured such that the user cannot click on any
other forms within the application without first closing said form
(Similar to a message box), w/ or w/o multithreading?

Thanks,
Aaron

Author
10 Aug 2006 11:13 PM
Tom Shelton
Aaron wrote:
Show quoteHide quote
> Hi,
>
> 1.  Can a seperate thread create a form?
>
> I created some test code.  I have a sub Test that attempts to create
> and show a form, objFrmTest which is of type frmTest.   Button1 and
> Button2 exist on another form (not frmTest). Button1 attempts to run
> sub Test with another thread, which Button2 simply attempts to run sub
> Test.  The results, in short, are the Button1 does not work while
> Button2 does.  Also, once Button1 is run, neither will work properly
> there after.
>
> I setup some breakpoints and did found that in both cases, the creating
> thread sucessfully ran both the form constructor and the Load event.
> In spite of that though, Button1 cannot bring up frmTest.
>
>     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles Button1.Click
>         Dim thdTest As Thread
>         thdTest = New Thread(AddressOf Test)
>         thdTest.Name = "ThreadTest"
>         thdTest.Priority = ThreadPriority.Highest
>         thdTest.Start()
>     End Sub
>
>     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles Button2.Click
>         Test()
>     End Sub
>
>     Public Sub Test()
>         If objFrmDiscrepancy Is Nothing Then
>             objFrmDiscrepancy = New frmDiscrepancy
>         ElseIf objFrmDiscrepancy.IsDisposed Then
>             objFrmDiscrepancy = Nothing
>             objFrmDiscrepancy = New frmDiscrepancy
>         End If
>
>         objFrmDiscrepancy.Show()
>         objFrmDiscrepancy.WindowState = FormWindowState.Normal
>     End Sub
>

It sure is - but you need to have a message pump on the second thread,
or the form will simply exit (Application.Run), see my example code
below (note - if you remove the call to thrd.IsBackground, the child
forms will continue to run even when you close form1):

' Form1
Option Strict On
Option Explicit On

Imports System
Imports System.Threading

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
    <System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.Button1.Location = New System.Drawing.Point(0, 0)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(216, 70)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(216, 70)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
        Dim thrd As New Thread(AddressOf ShowForm2)
        thrd.IsBackground = True
        thrd.Start()
    End Sub

    Private Sub ShowForm2()
        Application.Run(New Form2)
    End Sub
End Class

' form2
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, 122)
        Me.Name = "Form2"
        Me.Text = "Form2"

    End Sub

#End Region

End Class


> 2.  Assuming that a thread can create a form, will all the event
> handlers on the form execute against the primary thread (default
> thread? application thread?) or the thread that created it?
>

On the thread that the form is on - since that is where the messag pump
lives.

> 3.  Can a form be configured such that the user cannot click on any
> other forms within the application without first closing said form
> (Similar to a message box), w/ or w/o multithreading?

Sure, form.ShowDialog...  Of course, this will only be thread modal :)
If you use showdialog on a secondary thread, it will only block forms
on that thread.

--
Tom Shelton [MVP]