.NET Framework Bookmark and Share   
 index > Windows Presentation Foundation (WPF) > Parameter Mismatch Exception if VB (WPF) with BeginInvoke Method (new to threading)
 

Parameter Mismatch Exception if VB (WPF) with BeginInvoke Method (new to threading)

Hi, I am new to the multithreading concept, and I'm not sure if I completely understand it yet but regardless, I need to find out why this error is happening. I'm using VS 2010 Professional Beta 1 & .NET Framework 4.0 (have also tried this in VB Express 2008). I have a few questions that I would like answered. What I am trying to do is run a background thread to search through a string array of file names. In the process I need to make sure that my background thread has access to the UI thread so that it can update the controls and have the UI remain responsive. I think that I have this part down (will show code soon), but I think that I am not completely understanding how to use Lambada expressions, so here's my code:

If Not pbResults.Dispatcher.Thread Is searchThread Then
        pbResults.Dispatcher.BeginInvoke(Sub() pbResults.Value = (i / UBound(strFiles)) * 100, New Object() {Nothing})
End If
pbResults.Value = (i / UBound(strFiles)) * 100
This is the code that throws the ParameterMismatchException. I am unsure of two things, the syntax and usage of the Lambada expression and also if I am checking for the background thread's access to the UI thread correctly. Thanks in advance for any help.
Snake22
Unless you are using something very, very, very specific, use System.ComponentModel.BackgroundWorker class. I implements events on the UI thread side and takes care of all the troubles you're finding.
Bigsby, Lisboa, Portugal - O que for, quando for, é que será o que é... http://bigsby.eu
Bigsby
Thanks for your help, I'll give it a shot.
Snake22
Ok, I tried the background worker with no results. I am getting the error the the BeginInvoke method is supposed to avoid, which is the background thread (worker)does not have access to the UI thread. Here is where I get the error:
    Private Sub searchThread_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles searchThread.DoWork
        If txtSearchString.Text <> "" Then
            Search(txtSearchString.Text)
        End If
    End Sub
I'm not really sure what I am supposed to do... do I still have to invoke the progressbar or the window etc... ? Thanks again.
Snake22
That's when you use BackgroundWorker.ReportProgress method that raises the ProgressChanged event that lives on the UI thread.
Bigsby, Lisboa, Portugal - O que for, quando for, é que será o que é... http://bigsby.eu
Bigsby
Ok, I got the worker running correctly with no errors (it didn't take me 2 hours... I had class, so sorry for not responding in a while). But the next problem is that the UI is still unresponsive during the search routine. Is there a certain way that I should be implementing the search routine so that the UI remains responsive? Here's the routine I made for the purposes of this small application:

    Private Sub Search(ByVal strMatch As String)
        Dim strSearchArray() As String
        Dim iCurrent As Integer = 0
        Dim strSearchWords() As String = strMatch.Split(" ")
        strResults = Nothing
        If strMatch <> "" Then
            Dim iFileBound As Integer = UBound(strFiles)
            Dim iCurrentLoop As Integer = 0
            For i As Integer = 0 To iFileBound
                iCurrentLoop = i
                strSearchArray = strFiles(i).Split("\")
                For x As Integer = 0 To UBound(strSearchArray)
                    If LCase(strSearchArray(x)) = LCase(strMatch) Then
                        ReDim Preserve strResults(iCurrent)
                        strResults(iCurrent) = strFiles(i)
                        iCurrent += 1
                    End If
                    If strSearchWords.Count > 1 Then
                        For intCount As Integer = 0 To UBound(strSearchWords)
                            If LCase(strSearchWords(intCount)) = LCase(strMatch) Then
                                ReDim Preserve strResults(iCurrent)
                                strResults(iCurrent) = strFiles(i)
                                iCurrent += 1
                            End If
                        Next
                    End If
                Next
                If InStr(1, LCase(strFiles(i)), LCase(strMatch)) > 0 Then
                    ReDim Preserve strResults(iCurrent)
                    strResults(iCurrent) = strFiles(i)
                    iCurrent += 1
                End If
                searchThread.ReportProgress((i / iFileBound) * 100)
            Next
        End If
    End Sub
It makes sense why it is not updating the UI in real time, because the routine is pretty much a few loops. I was under the impression that the background worker would negate that though... am I wrong? Thanks again.
Snake22
What matters isn't really the method you're running with the BackgroundWorker but the way you're setting the BackgroundWorker.

If it's set correctly there should be no UI interference unless you have tons of ReportProgress calls.

Can you provide your BackgroundWorker setting and calling?
Bigsby, Lisboa, Portugal - O que for, quando for, é que será o que é... http://bigsby.eu
Bigsby
I have the background worker named searchThread declared as a withevents variable:

    Private WithEvents searchThread As System.ComponentModel.BackgroundWorker
This is where I initialize an instance of the BackgroundWorker class (when the search button is pressed):

    Private Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnSearch.Click
        If strDirectory <> "" Then
            If Not strFiles Is Nothing Then
                If strFiles.Length > 0 Then
                    If txtSearchString.Text <> "" Then
                        lstResults.Items.Clear()
                        Try
                            searchThread = New System.ComponentModel.BackgroundWorker
                            searchThread.WorkerReportsProgress = True
                            searchThread.RunWorkerAsync(txtSearchString.Text)
                        Catch ex As Exception
                            MsgBox(ex.Message)
                            Exit Sub
                        End Try
                    End If
                End If
            End If
        End If
    End Sub
Those are the only instances in the code that I reference the worker other than to report the progress in the search routine. Thanks again.
Snake22
You must have DoWork and ProgressChanged handlers some where.
How many times is ReportProgress call and with what interval?
What happens on ProgressChanged handler?

Bigsby, Lisboa, Portugal - O que for, quando for, é que será o que é... http://bigsby.eu
Bigsby
Oh, sorry about that:

    Private Sub searchThread_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles searchThread.DoWork
        Search(e.Argument)
    End Sub

    Private Sub searchThread_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles searchThread.ProgressChanged
        pbResults.Value = e.ProgressPercentage
        If e.ProgressPercentage >= 100 Then
            If Not strResults Is Nothing Then
                For Each sResult As String In strResults
                    If Not sResult Is Nothing Then
                        lstResults.Items.Add(sResult)
                    End If
                Next
            End If
        End If
    End Sub
Snake22
The only time I call ReportProgress is in the search routine after it is done analyzing each file.
Snake22
What is the typical value for iFileBound when you run the search? Remember it's only necessary to call ReportProgress when you actually have something to change in the UI, so there's no point in calling it ifthe progress has only changed by 0.001%. As the other poster stated, you could be calling it too often.
dekurver
iFileBound could be anywhere from 0 to infinity really, it depends on the directory that is selected. That seems to be irrelavent though because I've tested it in a directory with around 200 files and another with 50 or so files, and still the UI does not update.
Snake22
That's a complete different matter. If you set a breakpoint here:

lstResults.Items.Add(sResult)
is it hit?
Bigsby, Lisboa, Portugal - O que for, quando for, é que será o que é... http://bigsby.eu
Bigsby
If you stick a "When Hit" breakpoint (right-click on the breakpoint and select "When Hit") on the line that updates the progress barand print out the ProgressPercentage value, do you seethe percentage valuesthat you would expect to see?
dekurver

The lstResults breakpoint does hit, and when I do a "when hit" breakpoint I do see the values that I expect to see. I'm also noticing that my search routine returns several duplicate entires, and I've already tried doing:

If strResults.Contains(strFiles(i)) = False Then
' resize array and set new value
End If
That method returns duplicate results, and I'm not sure why...
Snake22
I've found a new symptom... and it points towards something in the search routine. When the search term is greater than 1 character in length, the UI is not updated. However, when the search term is only one character it does update the UI... I'm not really sure what this means but I will figure it out sooner or later.

Update: After further debugging, I've found that if the search term contains more than one word, it will also update the UI.
Snake22

You can use google to search for other answers

Custom Search

More Threads

• extending ModelVisual3D
• WrapPanel and HorizontalAlignment="Center" not working as expected ?
• Is many DrawingVisual's ok? (>10000)
• Need help about idea of sortable combobox in grid
• TriggerAction cannot be inherited
• GridViewColumns - how to hide them???
• MessageBox prevent RoutedEvent routing
• XAML Xml Binding
• itemscontrol template misbehaving!
• How to Set Column Header in DataTemplate