[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Multithreading question

Posted on 2015-02-19
14
Medium Priority
?
105 Views
Last Modified: 2015-02-19
Hi,

I am looking to spin up a new thread and wait for an amount of time before I kill it.

Is this possible to do whilst still allowing UI operations to update?

Below is a small example to show what I am struggling with:

Public Class Form1

    Sub HitMe()

        Do Until 1 = 2
            AppendMyText()
        Loop

    End Sub

    Private Sub btn_start(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnstart.Click
        Dim thr = New Threading.Thread(AddressOf HitMe)
        thr.IsBackground = True
        thr.Start()
        'thr.Join(10000) 'give it 10 seconds to run

    End Sub

    Sub AppendMyText()
        If Me.InvokeRequired Then
            Me.BeginInvoke(New MethodInvoker(Sub() AppendMyText()))
        Else
            Me.Textbox1.AppendText(Now.ToString & vbNewLine)
            Me.Textbox1.ScrollToCaret()
        End If
    End Sub

End Class

Open in new window


If I rem out the Thread.Join line, then the thread will be aborted after 10 seconds as I desire, but no textbox updates happen.

I would like to both have my cake and eat it if possible...
0
Comment
Question by:JedNebula
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 2
14 Comments
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 40618672
I suspect you just aren't giving the UI a chance to update because of the continual changing of the text - give something like the following a try.  It might need some adjustment with the DoEvents call.

Sub HitMe()

        Do Until 1 = 2
            AppendMyText()
DoEvents
        Loop

    End Sub
0
 
LVL 1

Author Comment

by:JedNebula
ID: 40618684
Hi Andy,

Thank you for the reply, but a DoEvents doesn't help because the UI thread is stuck waiting on the Join line.

Regards,

Rawden.
0
 
LVL 36

Accepted Solution

by:
Kimputer earned 1000 total points
ID: 40618748
How about using Timers (for both the Do Until madness, as well as the stopping at 10 seconds)
0
Nothing ever in the clear!

This technical paper will help you implement VMware’s VM encryption as well as implement Veeam encryption which together will achieve the nothing ever in the clear goal. If a bad guy steals VMs, backups or traffic they get nothing.

 
LVL 1

Author Comment

by:JedNebula
ID: 40618761
I did try that, but it didn't seem to quit the thread properly.

Used this example:
http://www.codeproject.com/Questions/528196/SettingplusTimeoutplusinplusvb-net

If someone could put a quick working example together I would be really grateful.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 40618820
Before one gets too much in detail this looks to be a very artificial example.  Very likely the problem is what I said in my first comment.  

If that is the case then would your real requirement have the same problem?
(You do not have to 'join' threads to allow something to be calculated in one thread and have results displayed in the other.)
0
 
LVL 1

Author Comment

by:JedNebula
ID: 40618839
HI Andy,

I only tried using the thread.join due to the comments I found here:
http://stackoverflow.com/questions/321779/to-currentthread-abort-or-not-to-currentthread-abort

I did try your suggestion of the DoEvents in my test project, but it didn't make any difference. I can post it online if you like?
0
 
LVL 36

Expert Comment

by:Kimputer
ID: 40618842
Here's a working example:

Public Class Form1


    Sub AppendMyText()
        If Me.InvokeRequired Then
            Me.BeginInvoke(New MethodInvoker(Sub() AppendMyText()))
        Else
            Me.Textbox1.AppendText(Now.ToString & vbNewLine)
            Me.Textbox1.ScrollToCaret()
        End If
    End Sub


    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        BackgroundWorker1.CancelAsync()
        Timer1.Enabled = False
    End Sub

    Private Sub btnstart_Click(sender As Object, e As EventArgs) Handles btnstart.Click
        BackgroundWorker1.WorkerSupportsCancellation = True
        BackgroundWorker1.RunWorkerAsync()
        Timer1.Enabled = True
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork


        Dim i = 1
        While True
            i += 1
            If ((i Mod 1000) = 0) Then
                AppendMyText()
            End If
            If (BackgroundWorker1.CancellationPending) Then
                e.Cancel = True
                Exit While
            End If
            Application.DoEvents()
        End While

    End Sub


    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        If (e.Cancelled) Then
            MsgBox("Canceled")
        End If

    End Sub
End Class

Open in new window


Obviously you were overloading the application, so that's why I added the "If ((i Mod 1000) = 0) Then" to make it slightly more realistic (next time let the while loop be realistic as well as what's inside it..
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 40618866
OK, looked at that link - so why do you need the join
0
 
LVL 1

Author Comment

by:JedNebula
ID: 40618894
Thank you Kimputer. Just trying your example. Looks good initially. Thank you.

Andy, occasionally my worker routine was 'held up' by some process outside of my control. I need a way to cut it short after an amount of time so that the app can continue to run other tasks.

My real-world app runs some important tasks at 5 am in preparation for the working day when people arrive, but recently the app has been held up on one of the early running tasks and then I have to dial in and kill the errant process it is depending on.

I will spend some time later working out why the external resource was taking much longer than expected, but this question is about putting a fail-safe in place.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 40619010
>>I need a way to cut it short after an amount of time so that the app can continue to run other tasks.

If a thread is running/stopped that should have no effect on the rest of the app.  If it does then it sounds like the interaction between the thread and the UI app is problematic.  (The thread forces the app to stop or the app is stopped to wait for the thread - either way is bad programming).
0
 
LVL 1

Author Comment

by:JedNebula
ID: 40619021
Although I am running a multi-threaded application, I still only fire off one task at a time. So if one takes longer than it should, the rest of the app doesn't hang - the UI still responds, but the app is waiting for that thread to finish before it can fire off another.
0
 
LVL 45

Assisted Solution

by:AndyAinscow
AndyAinscow earned 1000 total points
ID: 40619116
>>but the app is waiting for that thread to finish before it can fire off another.

So the tasks have to be run one after the other.  I still don't understand the need to 'join'.  When you want to spawn the second (or third....) you seem to say you check the state of the previous thread.  
If it is still running you can force it to finish (not really recommended) with the Abort command.  It is better to put some sort of flag condition so the thread will exit from it's loop (assuming it is in a loop for the calculation) and hence terminate itself.

This is C# but the principle is the same:
https://msdn.microsoft.com/en-us/library/7a2f3ay4.aspx
0
 
LVL 1

Author Comment

by:JedNebula
ID: 40619127
I don't think join is really the right method for me to use either. I only tried it because it recommended it in that article and I have to confess I only skim-read it. I was just looking for a thread.wait(x) method really, but that is what join seemed to do.

I think I have found a working solution now. I'll post it in a sec.
0
 
LVL 1

Author Comment

by:JedNebula
ID: 40619133
My working code:

Imports System.ComponentModel

Public Class Form1

    Private WithEvents tmr As Timer
    Private t As Threading.Thread

    Sub AppendMyText(text As String)
        If Me.Textbox1.IsDisposed Then Exit Sub
        If Me.Textbox1.InvokeRequired Then
            Me.Textbox1.BeginInvoke(New MethodInvoker(Sub() AppendMyText(text)))
        Else
            Me.Textbox1.AppendText(text & vbNewLine)
            Me.Textbox1.ScrollToCaret()
        End If
    End Sub

    Sub TheWork()
        Dim tc As Long
        Dim counter As Long
        While True

            tc = Environment.TickCount
            If tc Mod 1000 = 0 Then
                If tc <> counter Then
                    counter = tc
                    AppendMyText(Now.ToString)
                End If

            End If
            Application.DoEvents()
        End While

    End Sub
    Private Sub btnstart_Click(sender As Object, e As EventArgs) Handles btnstart.Click
        t = New Threading.Thread(AddressOf TheWork)
        t.IsBackground = True
        t.Start()
        tmr = New Timer
        tmr.Interval = 15000
        tmr.Enabled = True
    End Sub

    Private Sub tmr_Tick(sender As Object, e As EventArgs) Handles tmr.Tick
        tmr.Enabled = False
        If t IsNot Nothing Then
            t.Abort()
            t = Nothing
            Textbox1.Clear()
        End If
    End Sub
End Class

Open in new window

0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

650 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question