Solved

Multithreading question

Posted on 2015-02-19
14
83 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
  • 7
  • 5
  • 2
14 Comments
 
LVL 44

Expert Comment

by:AndyAinscow
Comment Utility
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
Comment Utility
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 35

Accepted Solution

by:
Kimputer earned 250 total points
Comment Utility
How about using Timers (for both the Do Until madness, as well as the stopping at 10 seconds)
0
 
LVL 1

Author Comment

by:JedNebula
Comment Utility
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 44

Expert Comment

by:AndyAinscow
Comment Utility
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
Comment Utility
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 35

Expert Comment

by:Kimputer
Comment Utility
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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 44

Expert Comment

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

Author Comment

by:JedNebula
Comment Utility
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 44

Expert Comment

by:AndyAinscow
Comment Utility
>>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
Comment Utility
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 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 250 total points
Comment Utility
>>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
Comment Utility
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
Comment Utility
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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
How do I get the unique ID after insert? 87 87
Encryption Decryption in Oracle 12 59
asp.net mvc5 3 35
Total in textboxes 9 34
This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now