Results 1 to 9 of 9

Thread: Func(Of Boolean) issues.

  1. #1

    Thread Starter
    Hyperactive Member Troy Lundin's Avatar
    Join Date
    May 2006
    Posts
    489

    Func(Of Boolean) issues.

    Good evening.

    I am using Func(Of Boolean) as a conditional, but it doesn't seem to be working correctly. Even though the function returns False, when I use If Condition() Then... it still passes. I am now sure what is going on. I created a gif of the problem for those that want to see it in action. I had to put it in a zip because it kept uploading as a jpg.

    Thanks.
    Attached Files Attached Files

  2. #2
    PowerPoster make me rain's Avatar
    Join Date
    Sep 2008
    Location
    india/Hubli
    Posts
    2,208

    Re: Func(Of Boolean) issues.

    post the code ,
    probably none will check your attachment
    The averted nuclear war
    My notes:

    PrOtect your PC. MSDN Functions .OOP LINUX forum
    .LINQ LINQ videous
    If some one helps you please rate them with out fail , forum doesn't expects any thing other than this

  3. #3
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Func(Of Boolean) issues.

    Please just post the code next time. An animated gif in a zip file is one of the more difficult ways to share code, most people won't go through the multi-step process to view it. I can't even pause it to study the code! It took me at least 10x longer to figure out what was going on, and since I can't see all the methods I can only speculate. Here's what I think:

    • For the function to return false, then BFF.Main.Game must be nonzero. Nothing in your GIF proves this is the case. Have you verified that the value is indeed nonzero? How?
    • There's a slight chance you're confused about closures. Are you aware cond will always use the current value of BFF.Main.Game, and not the value from the time it was created?
    • I don't see where PerformReadAction() is called. Are you sure that cond represents the function it is being given?


    My guess is one of those things is not operating the way you think. Give it a shot, and if it's still failing, change cond to always return False. Does it still appear to always return true? Now you know for sure the function that PerformReadAction() executes is not cond.

    Here's a test application to run to prove to yourself that this indeed works:
    Code:
    Module Module1
    
        Sub Main()
            Dim value = 0
            Dim conditionalFunction = Function()
                                          Return value = 0
                                      End Function
            value = 10
            Console.WriteLine(TellMeWhatItReturns(conditionalFunction))
        End Sub
    
        Function TellMeWhatItReturns(ByVal toExecute As Func(Of Boolean)) As Boolean
            Return toExecute()
        End Function
    
    End Module
    Last edited by Sitten Spynne; Aug 24th, 2015 at 09:47 AM.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  4. #4

    Thread Starter
    Hyperactive Member Troy Lundin's Avatar
    Join Date
    May 2006
    Posts
    489

    Re: Func(Of Boolean) issues.

    Code.

    vb.net Code:
    1. Namespace FF1
    2.     Public Class Character
    3.  
    4.         Dim cond As Func(Of Boolean) = Function()
    5.                                            If BFF.Main.Game = 0 Then
    6.                                                Return True
    7.                                            Else
    8.                                                Return False
    9.                                            End If
    10.         End Function
    11.  
    12.     End Class
    13. End Namespace

    When I step through and get to PerformReadAction, the autos window shows the following:
    Code:
    ‡		BFF.FF1.Character.<closure>.<lambda0-0> returned	False	Boolean
    That shows that it is truly returning False once I get to the PerformReadAction method.

    About your points:
    1) BFF.Main.Game is equal to 1, which is why it chooses Return False in the gif.
    2) The reason I use them is because of their dynamic nature; I want to use it as a conditional. PerformReadAction is called in a thread, and it checks the value of the Condition parameter each time. It needs to be dynamic.
    3) I apologize. I thought it was in the gif. Below is the code where it is called.

    vb.net Code:
    1. Sub SetReadAction(Action As Action(Of ListBox), Optional Condition As Func(Of Boolean) = Nothing)
    2.  
    3.         If Action Is Nothing Then
    4.             Common.GetError(New ArgumentNullException("Action cannot be Nothing."))
    5.             Exit Sub
    6.         End If
    7.  
    8.         ReadAction = Action
    9.  
    10.         If ReadActionThread Is Nothing OrElse Not ReadActionThread.IsAlive Then
    11.             ReadActionThread = New Thread(Sub()
    12.                                               While Not DesignMode
    13.                                                   PerformReadAction(Condition)
    14.                                                   Thread.CurrentThread.Join(25) ' Rest the thread to prevent lag.
    15.                                               End While
    16.                                           End Sub)
    17.  
    18.             ReadActionThread.IsBackground = True
    19.             ReadActionThread.Start()
    20.         End If
    21.  
    22.         ' Process paint messages.
    23.         If CBool(NativeMethods.GetQueueStatus(&H20)) Then
    24.             Application.DoEvents()
    25.         End If
    26.     End Sub

    I did change the code to always return false and it still passes.

    vb.net Code:
    1. Dim cond As Func(Of Boolean) = Function()
    2.                                            Return False
    3.                                        End Function

    Let me know if you need anything else. Thanks.
    Prefix has no suffix, but suffix has a prefix.

  5. #5
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Func(Of Boolean) issues.

    You mentioned a thread. This thread wouldn't happen to be trying to touch the UI, would it? That generally leads to weird behaviors.

    Also I'm still a little concerned by the Optional parameters. And I can't remember what the code in the gif said anymore, and this laptop doesn't run it well. The Autos window tells me what was going on at some moment in time, but have you tried putting breakpoints at relevant spots to watch it at the precise moments where it's called? Something's fishy, and it has the particular smell of "the function you are calling is not the function you expect". Since we're dealing with multiple layers of call stack, and threads, and closures, I can think of way too many potential problems to list.

    It'd be nice to see the entirety of the code files, so we could piece it all together.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  6. #6

    Thread Starter
    Hyperactive Member Troy Lundin's Avatar
    Join Date
    May 2006
    Posts
    489

    Re: Func(Of Boolean) issues.

    No, the thread does not touch the UI. The solution is thousands of lines of code. I'll try to provide the step by step.

    The initial call looks like this:

    vb Code:
    1. lbChar.ReadCustomText(Stats.Name, 4, cond)

    ReadCustomText definition looks like this:

    vb Code:
    1. Public Sub ReadCustomText(data As CustomText, count As Int32, Optional condition As Func(Of Boolean) = Nothing)
    2.  
    3.         SetReadAction(Sub(obj)
    4.  
    5.                           For i = 0 To count - 1
    6.  
    7.                               If lb.Items.Count <= i Then
    8.                                   lb.Items.Add(data(i).Value)
    9.                               Else
    10.                                   If Not lb.Items(i).ToString = data(i).Value Then
    11.                                       lb.Items(i) = data(i).Value
    12.                                   End If
    13.                               End If
    14.  
    15.                           Next
    16.  
    17.                           If lb.SelectedIndex = -1 AndAlso lb.Items.Count > 0 Then
    18.                               lb.SelectedIndex = 0
    19.                           End If
    20.  
    21.                           While lb.Items.Count > count
    22.                               lb.Items.RemoveAt(lb.Items.Count - 1)
    23.                           End While
    24.                       End Sub, condition)
    25.  
    26.     End Sub

    As you can see, condition is being passed through until it reaches the relevant function.

    SetReadAction look like this:

    vb Code:
    1. Sub SetReadAction(Action As Action(Of ListBox), Optional Condition As Func(Of Boolean) = Nothing)
    2.  
    3.         If Action Is Nothing Then
    4.             Common.GetError(New ArgumentNullException("Action cannot be Nothing."))
    5.             Exit Sub
    6.         End If
    7.  
    8.         ReadAction = Action
    9.  
    10.         If ReadActionThread Is Nothing OrElse Not ReadActionThread.IsAlive Then
    11.             ReadActionThread = New Thread(Sub()
    12.                                               While Not DesignMode
    13.                                                   PerformReadAction(Condition)
    14.                                                   Thread.CurrentThread.Join(25) ' Rest the thread to prevent lag.
    15.                                               End While
    16.                                           End Sub)
    17.  
    18.             ReadActionThread.IsBackground = True
    19.             ReadActionThread.Start()
    20.         End If
    21.  
    22.         ' Process paint messages.
    23.         If CBool(NativeMethods.GetQueueStatus(&H20)) Then
    24.             Application.DoEvents()
    25.         End If
    26.     End Sub

    It's a thread that continuously calls PerformReadAction. The point of Condition is to only read when it returns True. This way, I can control the thread easier.

    PerformReadAction looks like this:

    vb Code:
    1. Sub PerformReadAction(Optional Condition As Func(Of Boolean) = Nothing)
    2.         Dim sw As Stopwatch = Stopwatch.StartNew
    3.         If Condition Is Nothing OrElse Condition() Then
    4.             ExecuteSecure(Sub() ReadAction(Me))
    5.         End If
    6.  
    7.         If Not OnReadAction Is Nothing Then
    8.             If OnReadCondition Is Nothing OrElse OnReadCondition() Then
    9.                 ExecuteSecure(Sub() OnReadAction(Me))
    10.             End If
    11.         End If
    12.         sw.Stop()
    13.     End Sub

    From here, it invokes ReadAction. The definition of ReadAction is:

    vb Code:
    1. Private ReadAction As Action(Of ListBox)

    As you can see, Condition is simply passed through each method until it reaches PerformReadAction, where it is invoked. I said in my last post that Condition is False when it reaches PerformReadAction. Also, I only use Condition one time in this entire project. There are no other times it is used.

    Let me know if you need anything else.

  7. #7
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Func(Of Boolean) issues.

    Lambdas aren't broken, so somewhere along the chain there's a line of code that is doing something that's not quite what you expect. To find that, I find it helps to get someone to tell me what *they* think each line does. When we disagree, I find my mistake. You can have this conversation with the debugger, have you tried this?

    I'm assuming we're looking at this unit, because everything else seems simple.
    Code:
    If Condition Is Nothing OrElse Condition() Then
    	ExecuteSecure(Sub() ReadAction(Me))
    End If
    I don't know what you expect, because all I know is that you say something here is "wrong". I think this means you expect a False condition to NOT call ExecuteSecure(), but it IS calling ExecuteSecure. That's because if I pick this code apart, it says:

    "If there is no condition, or if the condition is true, then call ExecuteSecure() with a lambda that calls ReadAction()."

    We know the left half has to be False, because you've provided a call stack where Condition cannot be Nothing. So the only thing left is that Condition() must be returning True. This would be weird, since you hardcoded it to False. So let's do one last sanity check. Rewrite your code this way:

    Code:
            
    Dim noCondition As Boolean = Condition Is Nothing
    Dim conditionResult As Boolean = True
    If Not noCondition Then
    	conditionResult = Condition()
    End If
    If noCondition OrElse conditionResult Then ' Put a breakpoint here.
    	ExecuteSecure(Sub() ReadAction(Me))
    End If
    Put a breakpoint where indicated. Run your code until you hit the breakpoint. Look at the value of both variables. Are they "False" and "False"? Then all is working as expected and you need to explain what you think this code does so we can rewrite it to do that. Are they "False" and "True"? Then there is no other explanation than somehow cond is getting reassigned to a different lambda. That's difficult to unwind, especially when I have to ask for bits of code to be revealed.

    This is still a little iffy since we are on a thread, but if you've indeed hardcoded cond to return false we should've isolated that.

    So, to move forward:

    • I can't see what ExecuteSecure() does, but as of right now you are wrong when you say "the thread does not touch the UI". The thread calls a method that executes a lambda that updates a ListBox. That is most certainly touching the UI. Maybe ExecuteSecure() marshalls the call. I haven't seen proof, and strange things can happen in code when you do this.
    • You'd be surprised how fast I can dig through thousands of lines of code when I only care about 200 of them.
    • What are we actually doing? This seems like a complex architecture for anything, there might be an easier way to do this. Regardless, since all I know is "the if statement is acting up" it's hard for me to think about what could be going on in the larger context to cause it.


    That third point is starting to dig at me.

    It feels like this is some kind of editor for something in a game. It looks like the "ReadAction" thread is some kind of event loop: when buttons are clicked, you set its lambda. When it next ticks, it will evaluate a given condition and, if that condition is true, execute the lambda. Intuition tells me the condition lambda is there to make sure you don't continuously execute the ReadAction lambda.

    That seems a little overengineered to me. It would be much more straightforward if you just do the thing when you know you need to do it. This is why I kind of want to step back and evaluate the architecture. I lack the context to decide if this looks like a good idea.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  8. #8

    Thread Starter
    Hyperactive Member Troy Lundin's Avatar
    Join Date
    May 2006
    Posts
    489

    Re: Func(Of Boolean) issues.

    Ok, you earned my respect. Your code snippet worked, but why? Is it because it gets invoked before the If statement? So the value is set beforehand which makes it work?

    Also, it does seem over-engineered when looking at it like this, by itself. In fact, there are multiple controls that all use the same functionality. It's shared. You are correct that it's an editor for a game. Basically, I am reading values with the thread in a constant manner, so it's always up to date. Also, all these functions are in a separate class library that is shared by all my editors. This way, when I want to change some functionality, I only change it once instead having to update all the editors.

    If you still want to evaluate the architecture, I can message you a link to my source files. It would be nice to have someone other than myself look at this stuff.

    Edit: Here is ExecuteSecure()

    vb Code:
    1. Sub ExecuteSecure(a As Action)
    2.             If InvokeRequired Then
    3.                 BeginInvoke(a)
    4.             Else
    5.                 a()
    6.             End If
    7.     End Sub
    Last edited by Troy Lundin; Aug 25th, 2015 at 02:33 PM. Reason: Added code.
    Prefix has no suffix, but suffix has a prefix.

  9. #9
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Func(Of Boolean) issues.

    Hmm. That's kind of interesting. So you used the debugger and confirmed that the variables were "False" and "False"? I'm starting to think there's something subtle going on here. I tried a sample project but couldn't confirm any of the hypotheses I created.

    If you were capturing cond as part of a closure, I'd blame that. But you're not. I wrote both versions of the code and on my machine they both produce "false" and "false" and don't call ExecuteSecure(). As far as I can tell, they're identical and shouldn't produce different results.

    I keep wanting to blame the thread, but if you're hard-coding to False and not capturing cond in a closure you shouldn't be doing the things I worry are happening. It's a mystery. With the code before me, I can't answer it.

    ExecuteSecure() looks mostly like what I'd expect, but I suggest Invoke() instead of BeginInvoke(). Usually you pair Begin/End calls together. The documentation here seems to imply it's not required, but there's also no need to use BeginInvoke().

    I'm more interested in the source files to try and solve this dang puzzle than an architectural evaluation, if that makes any sense. I can't make a /promise/ I can look over everything, it'd definitely be the weekend before I could spend a lot of time on a review. But it sure would be nice to have a reason why this bit of code seems to misbehave.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

Posting Permissions

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



Click Here to Expand Forum to Full Width