Thread is not staring while calling a function cal

2020-04-28 22:43发布

问题:

I am using a thread to display a progress window while performing a time consuming operation(the for loop).after that operation I want to stop the thread.but the method "ShowProgressDialog" is not being called.I am using the same approach in other event which is working fine.below is the code.

Private Sub TSBRSToLoc_Click(sender As System.Object, e As System.EventArgs) Handles TSBRSToLoc.Click
    Try

        If Not BWRRStoLoc.IsBusy Then
            Dim backgroundThred As New Thread(AddressOf ShowProgressDialog)
            backgroundThred.IsBackground = True
            'Dim formProgree As New ProgressForm
            backgroundThred.Start()
            DisableBtns(sender)
            ProgressBarCompare.Value = 0
            lblProgStatus.Text = ""

            Dim filesSize As Long = 0
            For index As Integer = 0 To ObjlsViewCompare.Items.Count - 1
                Dim file As File = ObjlsViewCompare.GetModelObject(index)
                If Not file.Status = MatchStatus.MisingOnRackSpace Then
                    filesSize = filesSize + file.SizeOnRackSpace
                End If
            Next
            ProgressBarCompare.Maximum = filesSize
            ' formProgree.Close()
            backgroundThred.Abort()
            backgroundThred.Join()
            BWRRStoLoc.RunWorkerAsync()
        End If
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub

回答1:

There are several problems with your code:

1: You almost never want to call Thread.Abort - it may have unpredictable effects to do so, especially when one thread terminates another thread. See MSDN for more information.

The correct way to shut down a thread is to use some kind of message to tell the thread to exit by itself - set a static variable (that the thread checks periodically), use a synchronization object, etc. Thread.Abort() is a big no-no.

2: You have your logic backwards: you have your time-consuming operation on your main thread (the button click event handler shows that this is your main UI thread) and you're trying to show your progress dialog from a background thread.

It should be the other way around: you should set up all data for the background processing inside the click handler, show the progress dialog (assuming it's modeless) and then kick off the background thread that will do the processing.

During processing the background thread should keep notifying the progress window of its progress and once done, it should also notify the progress window of this fact.

Any time you need to notify your UI thread, you must properly marsal your call to the correct thread. This is because any UI elements may only be accessed from the thread that created it - for example, you cannot set the text of a label control from your worker thread without marshaling the call.

You need to use InvokeRequired / BeginInvoke() for marshaling. When calling BeginInvoke() you'll pass a delegate; something like this (sorry for the C# syntax, I'm not that familiar with VB.NET - should be easy to port this):

private void SomeEventHandler ( object oSender, EventArgs oE )
{
    if ( InvokeRequired )
    {
        MethodInvoker oDelegate = (MethodInvoker) delegate
        {
            SomeEventHandler ( oSender, oE );
        };

        BeginInvoke ( oDelegate );
        return;
    }
    else
    {
        // already on the correct thread; access UI controls here
    }
}

All this is because controls handle many of their property updates through messages and those messages must be delivered synchronously, in the correct order. The only way to ensure this (without some very complex coding) is to create all controls on the same thread where the thread runs a message pump.

See this question for more information about creating UI on a thread other than the main UI thread. (It's possible but you only want to do this if you really, really need that. That's fairly rare.)