robplatt Posted July 21, 2006 Posted July 21, 2006 I've read this post: http://www.xtremedotnettalk.com/showthread.php?t=76924 and have successfully created a thread without using the backgroudnworkerprocess doing this Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click Dim DBSyncThread As Threading.Thread Dim DBSyncThreadStart As New Threading.ThreadStart(AddressOf DBSync) DBSyncThread = New Threading.Thread(DBSyncThreadStart) DBSyncThread.IsBackground = True DBSyncThread.Name = "DBSync" DBSyncThread.Start() End Sub Private Sub DBSync() MsgBox("ehasdf boogieman") Functions.LogError("boogieman") End Sub the functions.logerror call is a class that takes the passed string and sticks it into a listview on my form then writes that string to a logfile as well. in the above code the messagebox pops up but the string 'boogieman' never makes it to the list. other areas of my project that arn't threaded use that logerror function very heavily (verbose). i just need to get this thread to be able to write to it too. I saw on the above url that I needed to use Dim threadfunction As New MethodInvoker(AddressOf nonthreadfunction) and in the thread i use Me.BeginInvoke(threadfunction) but those are sub routines and trying to tie in my function that passes the string just confuses the hell out of me. please advise. Quote
robplatt Posted July 21, 2006 Author Posted July 21, 2006 Well.. I Wrote up a similar app to start fresh that looks like this Public Class Form1 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click filllist() End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim t As Threading.Thread = New Threading.Thread(AddressOf filllist) t.IsBackground = True t.Start() End Sub Private Sub filllist() MsgBox("TEst") If Me.InvokeRequired = True Then Dim test = New Class1 test.tester("test") Dim mi As New MethodInvoker(AddressOf filllist) BeginInvoke(mi) Else Class1.tester("test") Dim i As Integer For i = 1 To 5000 ListBox1.Items.Add(i) Next End If End Sub End Class Public Class Class1 Public Shared Function tester(ByVal e As String) Form1.ListBox1.Items.Add(e) tester = 0 End Function End Class That actually works. So you get my idea. Soemtimes I need to add to a listbox under the normal thread, sometimes i need to add to it under a seperate thread. I have a feeling I'm not going about the best way, but it does work on THIS sample.. My big program its still not working. It wont fail with an error, but the text never makes it to the control. Quote
robplatt Posted July 21, 2006 Author Posted July 21, 2006 Nevermind, I spoke too soon, I wasn't paying attention to my own code, if it had worked I would see TWO 'test' in the listbox, im still only seeing the non threaded one. You get what I need now though. IF you guys can make the above code work. I'd be so greatful. Quote
Administrators PlausiblyDamp Posted July 22, 2006 Administrators Posted July 22, 2006 The first call to test.tester isn't being done on the UI Thread, therefore you are encountering the problem the BeginInvoke call is designed to fix. Also you could have done Class1.tester for both calls to the function rather than creating an instance of Class1. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
robplatt Posted July 22, 2006 Author Posted July 22, 2006 would you be kind enough to modify my example please so that it would work. Quote
Administrators PlausiblyDamp Posted July 22, 2006 Administrators Posted July 22, 2006 Everything works fine for me - both buttons populate the listbox correctly, the only problem is the 1st call to the .tester method. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
robplatt Posted July 23, 2006 Author Posted July 23, 2006 i know. thats what i need to happen. ya i got it figured out how to populate the boxes, but i hav to be able to call that function and pass data to it from one thread to the ui thread. see. the listbox is a log, very verbose of every action in the program, whats goign on, from what call to where, who clicked what etc. i have to be able to fill it from any thread. i wrote a shared function so that any form could pass data to it. the code above is just a sample. but like you said it wont work. populating the listboxes was easy, you can methodinvoke a sub routine. how do i do it fo ra function? Quote
Administrators PlausiblyDamp Posted July 24, 2006 Administrators Posted July 24, 2006 The Form's .Invoke method has an overloaded version that allows you to pass in an array of Parameters to the function itself. I've just tweaked your code so the check fo InvokeRequired is done inside the Class1.tester method rather than the calling method. The MethodInvoker delegate doesn't allow for parameters / return types so I've also defined a custom delegate for the tester method. Public Class Form1 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click filllist() End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim t As Threading.Thread = New Threading.Thread(AddressOf filllist) t.IsBackground = True t.Start() End Sub Private Sub filllist() Dim i As Integer For i = 1 To 5000 Class1.tester(i.ToString()) Next End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Class1.OutputForm = Me End Sub End Class Public Class Class1 Public Delegate Function TesterDelegate(ByVal e As String) As Integer Public Shared OutputForm As Form1 Public Shared Function tester(ByVal e As String) As Integer If OutputForm.InvokeRequired Then Dim o() As Object = {e} Dim mi As New TesterDelegate(AddressOf tester) OutputForm.Invoke(mi, o) Else OutputForm.ListBox1.Items.Add(e) End If tester = 0 End Function End Class I've changed a couple of other things - the filllist method now calls the .tester method rather than the listbox directly and the Class1 now stores a reference to the output form rather than going through the default instance of Form1. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
robplatt Posted July 24, 2006 Author Posted July 24, 2006 Thats exactly what I needed. Now to just plug it into my main program and hopefully everything goes smooth. thank you so much. Quote
robplatt Posted July 24, 2006 Author Posted July 24, 2006 I see only one problem, had i mentioned it earlier maybe it would have saved some time? but this function is called form multiple forms (thats why i put it in a class. except. im learning that more and more functions should probably go in classes, either way), so using outputform = form1, it wont work when form2 calls the same function in the same manner. Quote
Administrators PlausiblyDamp Posted July 24, 2006 Administrators Posted July 24, 2006 Will each form log to the same place or to a seperate place? If they are all loging to the same form then as long as the outputform is pointing to the correct form for the logging to be displayed on it shouldn't be a problem. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
robplatt Posted July 24, 2006 Author Posted July 24, 2006 Will each form log to the same place or to a seperate place? If they are all loging to the same form then as long as the outputform is pointing to the correct form for the logging to be displayed on it shouldn't be a problem. I went ahead and tested my application, and it worked fine. However its not correct. when form2 calls the same function outputform is stil = to form1. if i set class1.outputform = me on form2_load() then that would be correct, but what happens when form1 calls that function again. i could see this being a problem, what happens if i always use the methodinvoke, regardless if its needed or not. edit... i see that outputform has to = the form im writing the data to, which is the listview on form1. so this should always work. nevermind my previous rant, im still learning. :) Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.