dcsimg
Results 1 to 7 of 7

Thread: Using Thread

Hybrid View

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2014
    Posts
    346

    Using Thread

    I need to run the procedure which is sending emails to addresses from datatable. So, I need to use the loop. Because the process maybe very time consuming I wouldn't want to lock the application for the time of processing. Threading may be the solution. But I have not enough knowledge of using it.
    I started with the simple sample found on internet:
    Code:
    Imports System.Threading
    
    Public Class Form1
        Inherits System.Windows.Forms.Form
        ' Keep track of the thread so we can control it.
        Private m_Thread As Thread
    
        ' This value is incremented by the thread.
        Public Value As Integer = 0
    
        ' Make the thread but don't start it yet.
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
            ' Make a new counter object.
            Dim new_counter As New Counter(Me)
    
            ' Make the thread to run the object's Run method.
            m_Thread = New Thread(AddressOf new_counter.Run)
    
            ' Make this a background thread so it automatically
            ' ends when the form's thread ends.
            m_Thread.IsBackground = True
    
            btnStopThread.Enabled = False
            btnStartThread.Enabled = True
        End Sub
    
        ' Start the thread.
        Private Sub btnStartThread_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartThread.Click
            Debug.WriteLine("Starting thread")
            If (m_Thread.ThreadState And ThreadState.Unstarted) <> 0 Then
                ' The thread has never been started. Start it.
                m_Thread.Start()
            Else
                ' The thread is paused. Resume it.
                m_Thread.Resume()
            End If
    
            btnStopThread.Enabled = True
            btnStartThread.Enabled = False
        End Sub
    
        Private Sub btnStopThread_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStopThread.Click
            ' Suspend the thread.
            Debug.WriteLine("Suspending thread")
            m_Thread.Suspend()
    
            btnStopThread.Enabled = False
            btnStartThread.Enabled = True
        End Sub
    End Class
    
    ' This class's Run method displays a count in the Output window.
    Public Class Counter
        ' The form that owns the Value variable.
        Private m_MyForm As Form1
    
        Public Sub New(ByVal my_form As Form1)
            m_MyForm = my_form
        End Sub
    
        ' Count off seconds in the Output window.
        Public Sub Run()
            Try
                Do
                    ' Wait 1 second.
                    Thread.Sleep(1000)
    
                    ' Lock the form object. This doesn't do anything
                    ' to the form, it just means no other thread can
                    ' lock the form object until we release the lock.
                    SyncLock m_MyForm
                        ' Increment the form's Value.
                        m_MyForm.Value += 1
    
                        ' Write the value.
                        Debug.WriteLine("Thread: " & m_MyForm.Value)
                        m_MyForm.Label2.Text = "Thread: " & m_MyForm.Value
                        Form1.Label2.Text = "Thread: " & m_MyForm.Value
                    End SyncLock
                Loop
            Catch ex As ThreadAbortException
                ' This happens when the main program aborts the thread.
                Debug.WriteLine("Thread aborting")
            Catch ex As Exception
                ' An unexpected error.
                Debug.WriteLine("Unexpected error in thread" & vbCrLf & _
                    ex.Message)
            End Try
        End Sub
    End Class
    The original code works. I added the Label2 to see the processing on the form (my addition is colored with red). It produces an error :
    Cross-thread operation not valid: Control 'Label2' accessed from a thread other than the thread it was created on.
    What does this mean? And how to fix it?

    Thank you

  2. #2
    Wall Poster TysonLPrice's Avatar
    Join Date
    Sep 2002
    Location
    Columbus, Ohio
    Posts
    3,440

    Re: Using Thread

    I have always liked this example. It should run ASIS.

    'http://www.vbforums.com/showthread.php?680130-Correct-way-to-use-the-BackgroundWorker
    Please remember next time...elections matter!

  3. #3
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    34,908

    Re: Using Thread

    Just to add a bit of information to that: You used a thread, which is a pretty good way to go, but there is a better option, in this case, which is the BackGroundWorker. The BGW is really just something that manages a thread, so it is similar to what you are working with. However, it also raises a few events on the UI thread, which is really convenient. For one thing, you can raise the ReportProgress event from the BGW, and the UI thread (your form) can handle that event. In this case, you'd be raising that event instead of updating the label. In the form, you'd handle the event and set the label accordingly. That would get past the issue you are having (though there is another way, using Invoke). There is also an event that gets raised when the BGW completes, which may not be as useful to you.
    My usual boring signature: Nothing

  4. #4
    Wall Poster TysonLPrice's Avatar
    Join Date
    Sep 2002
    Location
    Columbus, Ohio
    Posts
    3,440

    Re: Using Thread

    Quote Originally Posted by Shaggy Hiker View Post
    Just to add a bit of information to that: You used a thread, which is a pretty good way to go, but there is a better option, in this case, which is the BackGroundWorker. The BGW is really just something that manages a thread, so it is similar to what you are working with. However, it also raises a few events on the UI thread, which is really convenient. For one thing, you can raise the ReportProgress event from the BGW, and the UI thread (your form) can handle that event. In this case, you'd be raising that event instead of updating the label. In the form, you'd handle the event and set the label accordingly. That would get past the issue you are having (though there is another way, using Invoke). There is also an event that gets raised when the BGW completes, which may not be as useful to you.
    OOPs...that is what I linked to - A background worker.
    Please remember next time...elections matter!

  5. #5
    Member Grant Swinger's Avatar
    Join Date
    Jul 2015
    Posts
    59

    Re: Using Thread

    Windows Forms controls are not thread safe. What this means is that only the thread that created the control can access it directly. This is a good thing because you don't want some thread which has no clue about the control's state to just barge in and change things.

    Read this tutorial.

    If you are new to threading start with the Background Worker as it is simple to understand and use. With that under your belt you can move on to more modern methods of threading.

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    34,908

    Re: Using Thread

    Yeah, I know, but I wanted the OP to know WHY you linked to that. A BGW would be ideal for this situation, though I don't want to discourage anybody from dealing with threads directly. After all, that's probably where learning starts when it comes to threading. There are lots of different threading things, all intended to make one or another piece easier, but starting with a Threading.Thread is a good place to begin.
    My usual boring signature: Nothing

  7. #7
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    104,715

    Re: Using Thread

    As suggested, a BackgroundWorker is a simplified option for using multithreading in a GUI. The point of the BackgroundWorker is to avoid using InvokeRequired, Invoke and BeginInvoke to determine what thread you're currently on and to marshal method calls to the UI thread. That's all done inside the BackgroundWorker code. You just have to call methods and handle events, which you've done many times before without multithreading. The one golden rule that you must observe when using the BackgroundWorker is DO NOT touch the UI in the DoWork event handler. That means getting or setting any property of a control or calling any method of a control. You also have to be careful of indirect access, e.g. modifying the data in a DataTable that is bound to a DataGridView. The grid is a control so any changes to bound data will end up getting or setting a property or calling a method. The short version of how to use a BackgroundWorker is as follows:

    Call RunWorkerAsync to start the background work.
    Handle the DoWork event and do the background work in the handler.
    To update the UI during the work, call ReportProgress and handle ProgressChanged.
    To update the UI after the work, handle RunWorkerCompleted.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width