How to Async



  • Found in real world production code:

    public class ServiceWrapper
    {
        //The variable below is hard to read, but if it was camel-case, this would be a bool called 
        //"formHasSoapCompleted1". The name alone should send chills down your spine. Honestly, the 
        //only good thing here is that there is no "formhassoapcompleted2"
        bool formhassoapcompleted1 = false;
        //Ah, love that 'l' Hungarian notation. Because it's a local variable, I guess. As opposed to the 
        //globals that don't really exist in C#.
        PriceSheet[] lPrcSheets;
    
        //snip out a dozen or so other state variables.
    
            public string InvokeSoap(methodArgs args)
            {
                //do some logging, etc
                soapClient client = new Client();
                client.doThingCompleted += new doThingEventHandler(MyCompletionMethod);
                client.doThingAsync(args);
    		
    		formhassoapcompleted1 = false;
                do
                {
                    string busyWork = "";
                }
                while (formhassoapcompleted1 == false)
    
                return lPrcSheets;
            }
    
            private void MyCompletionMethod(object sender, completedEventArgs e)
            {
                //In actuality, there's a couple hundred lines of code to transform 
                //SOAP client's class into ours, but I'll have mercy and omit that 
                //so you can see basically how this delegate works.
                lPrcSheets = e.priceSheets;
                formhassoapcompleted1 = true;
            }
    }
    

    Interestingly, the while loop gets optimized into an infinite loop when you compile for Release. They hadn't noticed it before because the production code was running in Debug mode. :open_mouth:



  • lPrcSheets in C# is amazing to me. Like, he seems to think:

    1. That variable is local (it's scoped to the class, actually)
    2. You need to use Hungarian in C#
    3. But the number of characters in a variable name is limited, so you better abbreviate "Price"

    @Pharylon said:

    do
    {
    string busyWork = "";
    }
    while (formhassoapcompleted1 == false)

    Even if you're gonna do this the rock-stupid way, how about a Thread.Sleep(), idiot? That poor CPU.

    @Pharylon said:

    Interestingly, the while loop gets optimized into an infinite loop when you compile for Release.

    That seems to be a 100% sensible optimization. I don't think the C# compiler is designed to compensate for "another thread came in here and shat all over this thread's variable".

    There might be a way to tell C# that's what you expect to happen but, uh. Well. They probably also didn't anticipate someone wanting to "de-async" an already async function.

    I have no idea what SOAP library that code's using, but Microsoft's seems to already have a synchronous version: https://msdn.microsoft.com/en-us/library/microsoft.web.services2.messaging.soapsender.send.aspx



  • @blakeyrat said:

    There might be a way to tell C# that's what you expect to happen but, uh. Well.
    volatile.@blakeyrat said:
    They probably also didn't anticipate someone wanting to "de-async" an already async function.
    They did, which is why they documented (in the Long Long Ago, the Before Times, the Early Days) how to do it with semaphores and WaitOne/WaitAny/WaitAll; they were reluctant to provide a batteries-included solution as inefficient and insufficiently generic. Now the guidance is to use the Task Parallel Library's TaskCompletionSource monkeywrench, although you get none of the usual benefits from doing so here.



  • Guess the l might be for list?



  • @TwelveBaud said:

    volatile.

    Well there you go. Now is there any code that uses that keyword and isn't also a HUGE WTF-in-progress?


  • Winner of the 2016 Presidential Election

    @blakeyrat said:

    Well there you go. Now is there any code that uses that keyword and isn't also a HUGE WTF-in-progress?

    Depends on the language. In C++, it's almost always wrong, unless you're writing drivers and your hardware is doing strange stuff.

    In Java, it can be useful if you want AtomicInteger without the overhead of an actual Object.

    I don't know C# too well, maybe the same as Java?


  • Discourse touched me in a no-no place

    @blakeyrat said:

    I don't think the C# compiler is designed to compensate for "another thread came in here and shat all over this thread's variable".

    Yes, but you have to code for it--you use BeginInvoke, Invoke, and EndInvoke. The common use case is exactly for "variables on a UI thread that are altered from a non-UI thread" and most System.Windows.Forms classes have at least some support built-in for it--you'll see comments about some fields and methods being thread-safe vs some that say "only call on a UI thread" or the like.


  • Discourse touched me in a no-no place

    @blakeyrat said:

    "another thread came in here and shat all over this thread's variable

    IF anyone cares, here's the correct way to do it:



  • @asdf said:

    In Java, it can be useful if you want AtomicInteger without the overhead of an actual Objectbut you dont want to do atomic operations with it.

    Volatile tells the jvm that the variable may be modified by outside processes, it might (I don't think so, but I don't exactly remember or care) allow atomic access (eg of longs on a 32-bit machine, where the vm reads the first half from memory, another process modifies the data, then the vm reads the next half from memory), it definitely doesn't protect against concurrent read-modify-write.



  • @asdf said:

    unless you're writing drivers and your hardware is doing strange stuff.

    Hardware changing the value of a status register is not "strange stuff;" it's very normal for hardware to do.


  • Winner of the 2016 Presidential Election

    @HardwareGeek said:

    Hardware changing the value of a status register is not "strange stuff;" it's very normal for hardware to do.

    I know, but everything hardware does is "strange stuff" to me. ;)


  • Winner of the 2016 Presidential Election

    @Buddy said:

    it definitely doesn't protect against concurrent read-modify-write

    True, what I wrote was BS.

    I've seen valid uses of volatile in Java, though. I'll try to find the code again…



  • @FrostCat said:

    IF anyone cares, here's the correct way to do it:

    You better properly source that SchmuckOverflow link you're about to post.

    @FrostCat said:

    https://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

    Oh, sorry, my mistake, I didn't see the "correct" in your post. Never mind.


  • Discourse touched me in a no-no place

    @asdf said:

    I've seen valid uses of volatile in Java, though.

    Thread A writes, thread B reads. So flagging of things like the processing stage of the code, etc. It's a bit lighter weight than a full lock dance. Best not used with anything larger than an int


  • Winner of the 2016 Presidential Election

    I think in our case it was a more complex lock-free algorithm. But yeah, volatile works as long as you don't need atomic updates or only one thread writes to the volatile int/bool.



  • @Pharylon said:

    ```cs
    //Ah, love that 'l' Hungarian notation. Because it's a local variable, I guess.

    
    Except it's not a local variable.

  • Discourse touched me in a no-no place

    @NedFodder said:

    Except it's not a local variable.

    Well, it was originally. Then it got moved.



  • @dkf said:

    @NedFodder said:
    Except it's not a local variable.

    Well, it was originally. Then it got moved.

    Fucking migrants.



  • @asdf said:

    I think in our case it was a more complex lock-free algorithm. But yeah, volatile works as long as you don't need atomic updates or only one thread writes to the volatile int/bool.

    I think I'd have to see some pretty convincing benchmarking before I took a risk on something like that.



  • @blakeyrat said:

    I think I'd have to see some pretty convincing benchmarking before I took a risk on something like that.

    Yup.

    What was that saying again? Something like: "There are two kinds of software engineers; those that don't understand multi-threading and those that think they understand multi-threading."



  • @Ragnax said:

    @blakeyrat said:
    I think I'd have to see some pretty convincing benchmarking before I took a risk on something like that.

    Yup.

    What was that saying again? Something like: "There are two kinds of software engineers; those that don't understand multi-threading and those that think they understand multi-threading."

    There are two kinds of software engineers. Those and that those don't that they understand they multi-threading understand , E_THREAD_ABORT


  • Discourse touched me in a no-no place

    You're ever so lucky if you get E_THREAD_ABORT. That's actually potentially recoverable from…


  • Impossible Mission Players - A

    @Ragnax said:

    those that don't understand multi-threading

    :wave: Especially when it's done by components not made by yourself and that causes all sorts of shenanigans that you weren't prepared for...



  • @Tsaukpaetra said:

    Especially when it's done by components not made by yourself and that causes all sorts of shenanigans that you weren't prepared for...

    I've had my fair share of being on the receiving end of those situations as well, yes.


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.