|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Threading...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. Regards Simon ps Previously posted by mistake to vb.controls group. -- ================================ Simon Verona Dealer Management Service Ltd Stewart House Centurion Business Park Julian Way Sheffield S9 1GD Tel: 0870 080 2300 Fax: 0870 735 0011 -- ================================ Simon Verona Dealer Management Service Ltd Stewart House Centurion Business Park Julian Way Sheffield S9 1GD Tel: 0870 080 2300 Fax: 0870 735 0011 well im kinda curious on why it looks like your attempting to show another
form on a different thread....are you meaning to put the form on another thread, and if so why? -- -iwdu15 Good question...
Maybe if I explain the application.... I have a main form, which displays a list of entries. The application allows you to click on an entry to open a form to view/update the details of that entry. However, I wanted to allow multiple entries to be displayed together. Also, I wanted to encapsulate the display of the form within a class (it is used in many parts of the application as well, so I felt it would be easier). If I display the form without creating the thread, the form dies as soon as the subroutine exits back to the main form (IIRC!), so I came up with this as a workaround. It also seemed to have the affect of making the application seem to run smoother (though that could just be me). If I don't create the thread and just use showdialog, then the original form is blocked until it returns. I don't know why it should be causing a problem, but if there is a better way of acheiving the same thing without creating the thread then I'm up for it! Regards Simon -- Show quoteHide quote================================ Simon Verona Dealer Management Service Ltd Stewart House Centurion Business Park Julian Way Sheffield S9 1GD Tel: 0870 080 2300 Fax: 0870 735 0011 "iwdu15" <jmmgoalsteratyahoodotcom> wrote in message news:C1079914-7732-4C59-A82A-2EFD1FE9AD01@microsoft.com... > well im kinda curious on why it looks like your attempting to show another > form on a different thread....are you meaning to put the form on another > thread, and if so why? > -- > -iwdu15 well, if you wan to do it that way, then make sure our thread safe. Threads
can only access objects they create, for instance your Form1 cannot access things on your other thread's form and vice versa, keep that in mind. To access methods on other threads, use the threads Invoke method, dont call the method directly. Keeping that in mind, there wouldnt be a need to call "ShowDialog" and show the form on a new thread....i dont know if that would cause issues or not, so your best bet would be calling "Show", not "ShowDialog" -- -iwdu15 if you want to show a new form on a different thread, then the new thread
must then create the form object: Private Delegate Sub delNewThread Private Sub btnNewThread_Click(...) Dim x as New delNewThread(AddressOf CreateNewFormThreadBegin) Me.Invoke(x) End Sub Private Sub CreateNewFormThreadBegin() Dim frm as New Form2 frm.ShowDialog() End Sub that will create a new form on a different thread then show it -- -iwdu15 Simon Verona wrote:
Show quoteHide quote > I think I'm doing this wrong : If this is what you want, why not just .Show (rather than .ShowDialog)> > 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. the form? Anyway... > I think you are falling foul of the rule whereby UI elements cannot be> 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. safely interacted with from threads other than their 'owning' thread - that on which they are created. So here the myFrm is created on the thread that enters this procedure, but then passed to a different thread to show itself. Thus this second thread will be accessing UI elements it didn't create -> bad. The fix (if there are deeper reasons why you need to do this sort of thing) is to move the form creation from before thread-creation to after it. That is, at the moment you are saying: Create form Create thread (giving it the form) Start thread - thread goes on to show form Instead you should say Create thread Start thread - thread goes on to create form, then show it. Probably the logical place for this new routine would be a Shared procedure in myFrm: Public Shared Sub NewShowDialog Dim f As New myFrm f.ShowDialog End Sub then replace your current myFunction with Dim t As New Thread(AddressOf myFrm.NewShowDialog) t.Start But please first consider my first question about .Show vs ..ShowDialog... -- Larry Lard Replies to group please When starting a new topic, please mention which version of VB/C# you are using See my previous reply, I've had problem with the form disappearing when the
subroutine exits... (I'm presuming the object is killed on exit?) I understand what you are saying about the frm creation and use being on seperate threads. I must admit to not thinking of having a shared entry on the form to display itself! Regards Simon -- Show quoteHide quote================================ Simon Verona Dealer Management Service Ltd Stewart House Centurion Business Park Julian Way Sheffield S9 1GD Tel: 0870 080 2300 Fax: 0870 735 0011 "Larry Lard" <larryl***@hotmail.com> wrote in message news:1153150234.509877.22680@m73g2000cwd.googlegroups.com... > > Simon Verona wrote: >> 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. > > If this is what you want, why not just .Show (rather than .ShowDialog) > the form? Anyway... > >> >> 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. > > I think you are falling foul of the rule whereby UI elements cannot be > safely interacted with from threads other than their 'owning' thread - > that on which they are created. So here the myFrm is created on the > thread that enters this procedure, but then passed to a different > thread to show itself. Thus this second thread will be accessing UI > elements it didn't create -> bad. > > The fix (if there are deeper reasons why you need to do this sort of > thing) is to move the form creation from before thread-creation to > after it. That is, at the moment you are saying: > > Create form > Create thread (giving it the form) > Start thread - thread goes on to show form > > Instead you should say > > Create thread > Start thread - thread goes on to create form, then show it. > > Probably the logical place for this new routine would be a Shared > procedure in myFrm: > > Public Shared Sub NewShowDialog > Dim f As New myFrm > f.ShowDialog > End Sub > > then replace your current myFunction with > > Dim t As New Thread(AddressOf myFrm.NewShowDialog) > t.Start > > But please first consider my first question about .Show vs > .ShowDialog... > > -- > Larry Lard > Replies to group please > When starting a new topic, please mention which version of VB/C# you > are using > Simon Verona wrote:
> See my previous reply, I've had problem with the form disappearing when the I'd be tempted to go back and re-examine that situation, to be honest. > subroutine exits... (I'm presuming the object is killed on exit?) To paint with a *very* broad brush, multi-threading is something you shouldn't do unless you quite obviously _must_. > The thought process there was that the behaviour of <creating a new > I understand what you are saying about the frm creation and use being on > seperate threads. I must admit to not thinking of having a shared entry on > the form to display itself! myFrm and displaying it> clearly 'belongs to' the myFrm class, but not to any particular instance of it => shared method. -- Larry Lard larryl***@googlemail.com The address is real, but unread - please reply to the group For VB and C# questions - tell us which version Larry
I had a go at implementing your thought, but of course, the "real" code is not quite as simple as the example I posted: The real code passes a variable through to the form when constructing ie dim frm as new myfrm(myvar) dim t as new threading.thread(addressof frm.myShowDialog) t.start I can't work out how to create a shared function that I can call on another thread AND pass a parameter! Regards Simon -- Show quoteHide quote================================ Simon Verona Dealer Management Service Ltd Stewart House Centurion Business Park Julian Way Sheffield S9 1GD Tel: 0870 080 2300 Fax: 0870 735 0011 "Larry Lard" <larryl***@hotmail.com> wrote in message news:1153150234.509877.22680@m73g2000cwd.googlegroups.com... > > Simon Verona wrote: >> 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. > > If this is what you want, why not just .Show (rather than .ShowDialog) > the form? Anyway... > >> >> 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. > > I think you are falling foul of the rule whereby UI elements cannot be > safely interacted with from threads other than their 'owning' thread - > that on which they are created. So here the myFrm is created on the > thread that enters this procedure, but then passed to a different > thread to show itself. Thus this second thread will be accessing UI > elements it didn't create -> bad. > > The fix (if there are deeper reasons why you need to do this sort of > thing) is to move the form creation from before thread-creation to > after it. That is, at the moment you are saying: > > Create form > Create thread (giving it the form) > Start thread - thread goes on to show form > > Instead you should say > > Create thread > Start thread - thread goes on to create form, then show it. > > Probably the logical place for this new routine would be a Shared > procedure in myFrm: > > Public Shared Sub NewShowDialog > Dim f As New myFrm > f.ShowDialog > End Sub > > then replace your current myFunction with > > Dim t As New Thread(AddressOf myFrm.NewShowDialog) > t.Start > > But please first consider my first question about .Show vs > .ShowDialog... > > -- > Larry Lard > Replies to group please > When starting a new topic, please mention which version of VB/C# you > are using > Thanks for the example...
However, I'm not 100% positive how I would modify your example to pass a variable to the form. I presume that I can't set a local private variable (declared outside of ay subroutines) and then access it from within the CreateNewFormThreadBegin sub? I'm presuming that can I can't directly pass any variables directly through to the CreateNewFromThreadBegin (ie modifying it to Private Sub CreateNewFromThreadBegin(myvar as string) ) Apologies if I've missed the obvious - Can I use the facts that it's 5pm and very hot to mitigate my stupidity? <G> Thanks Simon -- Show quoteHide quote================================ Simon Verona Dealer Management Service Ltd Stewart House Centurion Business Park Julian Way Sheffield S9 1GD Tel: 0870 080 2300 Fax: 0870 735 0011 "iwdu15" <jmmgoalsteratyahoodotcom> wrote in message news:D6016E94-C059-4376-9AD8-A664332939EB@microsoft.com... > look at my code example above > -- > -iwdu15 i appologize, i forgot to add the code to create a thread..silly me, heres
the updated code, im working on pass variables now...i forgot how to do it myself Private Delegate Sub delNewThreadBegin() Private Sub NewThreadBeginSub() Dim frm As New Form1 frm.ShowDialog() End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim thr As New Threading.Thread(AddressOf ThreadStart) thr.Start() End Sub Private Sub ThreadStart() Dim x As New delNewThreadBegin(AddressOf NewThreadBeginSub) Me.Invoke(x) End Sub -- -iwdu15 i cant figure it out rite now, im a 17 year old at work trying to multi task
and its nto working too well so my code doesnt even make sense to me....il write the answer when i get home, i have a few examples on my home computer -- -iwdu15 Simon Verona wrote:
Show quoteHide quote > I think I'm doing this wrong : Simon...> > 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. 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... -- Tom Shelton [MVP] Simon Verona wrote:
<snip> Show quoteHide quote > I have a class with a public shared method such as follows: <snip>> > 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). It's an error to access the method of a class derived from Control (which is the case of Form) from a thread other than the one where the object was created. You must use the object's InvokeRequired method to check if you're being called from another thread and if so (InvokeRequired returned True), use Invoke to call the desired method. The 'pattern' is somewhat like this: 'in myForm 'Must have the same signature of MyShowDialog Delegate Sub MyShowDialogCallback(Param as Integer) '... Sub MyShowDialog(Param As Integer) Static This As MyShowDialogCallback = AddressOf MyShowDialog If InvokeRequired Then BeginInvoke(This, New Object() {Param} ) Else 'Do your thing 'blah, blah, blah ShowDialog End If End Sub HTH. Regards, Branco.
Bug or Feature? CancelButton vs Escape Key
Copy / Paste, Excel To flexgrid An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in system.data.dll Public Structure Sendmessage problem help! Holding down a key HELP: Problem Hosting the "Simplest" of VB.NET Apps detect if running on a terminal server Deleting files using wildcards text editor |
|||||||||||||||||||||||