Book Review: C# 2008 and 2005 Threaded Programming: Beginner’s Guide

Note: The author of this book has requested that I remove their name from this blog post. I have done so in accordance with their wishes, editing comments as well.

Update (19th March 2009)

Debate around this review is getting heated. I stand by all the points I make about the text, but I’d like to clarify a few things:

  • If there are any ad hominem comments in the review against the author, please ignore them. I’m going to try to weed out any that I find, but if you spot one, please let me know and then ignore it. I feel very strongly that a review should be about the text of a book, not about its author. The text is what will inform the reader, not the author’s other work. I’m aware that the author has written many other books, and is generally well-regarded (as far as I can tell, anyway). That neither helps nor hinders the text. The same goes for me and the review, of course. Whether you know me or not, whether you’ve read anything else I’ve written or not, the review should stand on its own merits. This is not a popularity contest – it’s a discussion about a technical book.
  • The impression I’ve given in the review is almost entirely negative. This is because that’s the impression I received as a reader interested in accuracy and best practices. That does not mean that the book is entirely inaccurate – far from it. There are plenty of aspects where I have no particular issues with the accuracy. (The code style is more uniformly disagreeable to me, but that’s a subjective matter.) However, there is enough inaccuracy (and bad practice, in my view – somewhat subjective, but less so than the code style) to make that the dominant impression left with me, alongside my surprise that there’s no proper discussion of locking. As an analogy, imagine you go to a choral concert. Suppose the sopranos, altos and tenors are all perfectly in tune, but the basses are out of key the whole time. In some senses the concert would be 75% accurate – but the 25% inaccuracy would be enough to ruin it. So it is with technical books (not just this one) – it only takes a relatively small degree of inaccuracy to make the difference between a good book and a bad one. The bottom line is: even I don’t think everything or even most of what’s written in the book is wrong; there are enough problems to make me dislike it though.
  • I’ve made a few minor edits to the review just now, to address a few comments made so far. If some of the comments appear to be odd, that may be why!

Resources

  • Publisher’s page (Packt) – this is the cheapest way to buy the book as far as I can see
  • Sample code (49MB download! Mostly because it contains bin/obj directories for all solutions…)
  • Amazon or Barnes and Noble links if you don’t want to buy it directly
  • John Mueller’s review – a much more positive review than this one, which may prove an interesting counterbalance for readers. (Thanks to Erik for pointing out John’s review in the comments.)

Disclaimer

This book doesn’t really compete with C# in Depth, but obviously the very fact that it’s another book about C# at all means I’m probably not entirely unbiased. Arguably it also “competes” with my own (somewhat out of date now) threading article, although that’s not a monetary venture for me. I should also point out that my copy was sent to me for free, specifically for review, by Packt Publishing.

Audience and content

The book claims that “Where you are a beginner to working with threads or an old hand who is looking for a reference, this book should be on your desk.” In practice, I don’t think it’s really suitable as a reference. The kind of information you really want as a reference is hard to find amidst the bulk of the book, which is on-going examples. For the rest of this review I’ll regard the intended audience as just beginners.

The first chapter (out of 12; at 388 pages one of the nice things about this books it that it’s relatively slim) is introductory material about threads and processes, and why concurrency is important in the first place. After this one code-free chapter, the rest of the book is all example-based. The pattern goes something like this:

  • Give rough idea of what we’re building
  • Create first version of the code
  • Explain what it does and why it may not be ideal
  • Improve it
  • Explain how the improvements work
  • Move to next example or add new major feature

That sounds all very well, but I’ll get to my issues with it in a minute. Although the examples are constantly evolving, they essentially break down into these applications:

  • “Code cracking” (brute-forcing a 4 character code)
  • “Encrypting” SMS messages (not real encryption – no key – but a general CPU-intensive transformation)
  • Image processing to find and highlight “old stars” in NASA images
  • “Encrypting” several files
  • More image processing – adjusting the brightness of a large image and thumbnailing it

These are all Windows Forms applications, and are frankly pretty similar, all basically dealing with simple, embarrassingly parallel tasks. That’s not to say the author doesn’t get a fair set of different techniques and lessons out of them:

  • Keeping the UI thread free (and seeing what happens when you don’t)
  • Tips for debugging multi-threaded apps in Visual Studio
  • Showing the performance for individual processes using Task Manager and Windows Explorer
  • Using BackgroundWorker to update the UI
  • Queuing tasks in the system thread pool
  • Creating new threads explicitly
  • Using Control.Invoke/BeginInvoke to update the UI (although this comes very late in the book – chapter 10 out of 12)
  • Keeping tasks independent
  • Noting that sharing data between threads is difficult – but coming to the wrong conclusions (more later)
  • Using the Timer component (just the WinForms timer; not System.Threading.Timer, System.Web.UI.Timer or System.Timers.Timer) – although later on he uses a BackgroundWorker for a task much more suitable for a Timer.
  • A bit of OO design, although in a pretty botched way – the idea of having a general-purpose “parallel algorithm” class and a “parallel algorithm piece” class is reasonable, but it isn’t handled nearly as well as it might be
  • Fairly disastrous advice (IMO) about both I/O and the GC
  • Exception “handling” (where “swallowing exceptions and just reporting them with Debug.Print” counts as “handling” apparently)
  • Parallel Extensions from .NET 4.0, with both PLINQ and TPL

Unfortunately, this misses out some of the most important concepts in parallelism on .NET. The author frequently mentions locking, but only ever in a “we’re avoiding doing it” way. I find it absolutely incredible that a book on multi-threading in C# doesn’t even mention the “lock” keyword. Okay, it’s nice to be able to split tasks up completely independently where possible, but in the real world you sometimes have to use shared mutable state (or at least, it’s often the simplest approach).

When I first got the book, I looked up several entries in the index to see how they’d be handled. I was shocked to find that none of these have an index entry:

  • lock
  • volatile
  • memory model
  • Monitor
  • Wait or Pulse
  • BeginInvoke or Invoke
  • double-checked locking
  • mutable or immutable

The concept of accessing state from multiple threads is glossed over for the entirety of the book. Basically whenever multiple threads want to make their results available, they put them in different elements of an array or list. There’s an assumption that if you read from that array/list in a different thread, it’s all okay. Likewise there’s an assumption that it’s appropriate to read integer variables written to in one thread from another thread without any locking, volatility or use of the Interlocked class. I’ll come back to this topic when I tackle accuracy later on.

Style

This is a very informal book: something I have no problem with. English clearly isn’t the author’s first language, and although I don’t blame him for some of the clumsy wording in the book (e.g. “We will not leave behind the necessary pragmatism in order to improve performance within a reasonable developing time”) I do wish the book’s editorial team had done a better job in that respect. It’s tricky with technical books: non-technical editors have good reason to be wary of going too far, as small changes in wording can have make a large difference semantically, but it does make a big difference to a book’s readability when the language is clear and idiomatic. (As a side note, I feel incredibly fortunate to have English as my native tongue. I’m not fluent in any foreign languages, and I’m often amazed at how well others manage.)

There are other elements of the style of the book which I have much more of a problem with. The first is the way that the examples are handled. A very large proportion of the book is just lists of instructions: “add some using directives: <code>; add these variables: <code>; add this procedure: <code>; add another procedure <code>; add an event handler <code>” with just a sentence or two of explanation for each one as you go. There’s much more explanation after all the code has been added, but the way that the code is given makes it very hard to see what’s going on. We almost never get to see a whole class in one listing – it’s always broken up into using directives, variables, individual methods etc. This may not be too bad if you’re following along with the book at every single point, but it makes it very hard to just read. As a friend has commented, this content might work a lot better as a screencast, rather than as a book.

One detailed gripe: nearly every time a property is introduced, the author uses the phrase “we want to create a compact and reliable class” as a justification. There’s no explanation, and quite often the properties are mutable for no good reason (when a genuinely reliable class in a multi-threaded setting would be immutable). After a while it made me want to grind my teeth every time I saw it.

The feeling is very much that of a Head First book, but one which doesn’t work. For all my misgivings about Head First C# (which I believe is now very much better now that a large number of errors have been removed) the general style was very well handled. It’s not my preferred style to start with (particularly focusing on large GUIs instead of short, complete console apps) but I rarely felt particularly lost in the listings – there was usually enough context to hold onto. Here, I feel there’s very little context at all. If you accidentally miss out a step, you’ll have a really hard time working out which one it is or what’s wrong.

On top of this, there’s the bizarre storyline “explaining” all the listings. Apparently you (the reader) originally started out cracking a code, then got hired by some other crackers, then the FBI, then NASA. We are told of FBI agents getting us capuccinos, the NASA CIO wanting you to use the Parallel Extensions CTP so that they can get free licences for Visual Studio 2010 and all kinds of other oddities. We are constantly bombarded with plaudits about our threading capabilities – by the last chapter we’re regularly being called “experts” and “threading gurus” despite the fact that we wouldn’t have a clue what was going on if someone presented us with some code using a “lock” statement. This is all patronising in the extreme – and again, Head First C# (and  I suspect the rest of the Head First series) handles the “keep it informal but drive the topic forward” aspect a lot more successfully.

Finally, on the topic of style, I’d like to rant a bit about the coding style. It’s awful. Really awful. I realise that coding standards are to some extent a personal thing, but I object to code like this:

  • Pseudo-Hungarian (the type which uses “o” as a prefix for almost any object; not the type Peter likes) and the nature of every variable (local, parameter or instance variable) makes for horrendous variable names such as “prloOutputCharLabels”. It’s not even consistent – variables added by the designer only get a type designation prefix (lbl, but, pic) but no nature prefix. Aargh.
  • Methods are frequently camel-cased instead of Pascal-cased, e.g. “showFishes” and “checkCodeChar”. It’s possible that this is only true for private methods – a very quick flick through doesn’t reveal any public ones like this – but if so it’s inconsistently applied as there are certainly Pascal-cased private methods too. Some public properties combine both annoyances so far, with names such as “poThread” and “piBegin”.
  • Most (but not all) of the time the author declares all of a method’s variables at the top, even if they’re not used for a long time. This includes declarations of variables for use in loops. This took me right back to the 80s, writing ANSI C again. I believe that the ability to declare variables at the point of first use gives a significant improvement in readability. It’s easier to see where a variable will be used if its scope is limited, for example.
  • Using directives aren’t applied nearly thoroughly enough, leaving lots of explicit use of System.Diagnostics, System.Drawing, System.ComponentModel etc. Given the line length limitations in printed books, this is a real killer in terms of providing compact, readable code.
  • Speaking of line length limitations, it would be really useful to actually acknowledge them – if a comment is going to span two printed lines, starting just the first one with “//” and leaving the second indented but not really a comment isn’t a good idea.

So, we’ve got code broken up into chunks which breaks the flow of the code, and I don’t even like the style of the code. Still, I could live with that if it’s good quality code…

Accuracy and best practices

I’ve already indicated one of the significant problems I have with the book in terms of content: its complete absence of discussion about shared data and locking. Yes, this is a beginner’s book, and I wasn’t expecting the level of detail on the memory model which is present in Joe Duffy’s book (which I promise I’ll review soon) – but I’d certainly prefer to err on the side of safety. The book regularly just accesses data on one thread having written it on another, with no locking, volatility or use of Interlocked. This isn’t the sole bad practice, however, and it’s not limited to stylistic choices either. In the course of the book, we are told all of the items below (and more). Italics indicate what the book claims; regular type indicates my response. These aren’t verbatim quotes, but paraphrase:

  • Forcing garbage collection before starting a multi-threaded operation is a good idea. This is given as a sort of response to a screenshot of Process Explorer showing ugly memory usage. In fact, I can’t reproduce the kind of nasty graph that’s shown in the book, even with the code downloaded from the web site, but if I did see that there are definitely better ways of addressing it than forcing garbage collection. Disposing of Bitmaps appropriately would be a good start… as it is, each bitmap is going to hang around for at least one garbage collection cycle longer than it should, because we’ve got to wait for its finalizer to be executed. Making sure you dispose of objects appropriately is always a good idea – explicitly forcing the garbage collector is almost always a bad one. (Not absolutely always, but usually.)
  • WaitHandle.WaitAll has to run on an MTA thread – so let’s just change the [STAThread] line above the Main method to [MTAThread], with no warning that it’s a really bad idea to do that for Windows Forms. (Side-note: when trying to check that there really isn’t a warning, I had to spend a long time finding the section. The index doesn’t contain entries for MTAThread, STAThread, apartment, WaitHandle or WaitAll. In general the index could do with a lot of work. I’m painfully aware that indexing is a horrible task, but it’s important.)
  • Application.DoEvents() is a way of letting the UI process events. This is true – it’s also another really bad idea unless you absolutely have to use it. Re-entrancy is hard to debug – and not mentioned at all in the book, as far as I can tell.
  • Data streaming is wasteful, because two threads might both want to do I/O at the same time – it’s a better idea for each thread to load all the data it needs to and then start processing it. This is stated in a context where streaming is ideal – each thread just needs to process every line in a file. (Each thread is asked to process a different file.) There’s no dependency between the lines of the file. It’s an absolute gift – the buffering and pre-fetch techniques of Windows would guess we needed the next block of data before we ask for it, so the disk would be seeking while we’re encrypting, on each thread. At least, I strongly suspect it would – and I would profile the thing instead of just claiming that we’ve managed to avoid an I/O bottleneck by loading files in their entirety up-front. No mention is made of the fact that as soon as a bunch of big files are queued for encryption, you’ll have a bunch of threads all trying to load everything before they bother starting to do anything. Avoiding I/O contention is a tricky topic, and it deserves better than a couple of misleading paragraphs with no attempt at explaining what the benefits of streaming the data would be.
  • The thread pool is used to queue threads with work to do. If there are already lots of threads busy, the new threads will wait until the old ones have finished. Note the use of “threads” here – not tasks to run on a pool of existing threads, but threads. This would make the thread pool pointless – what is never explained in the book is that creating threads is a relatively expensive business, and you don’t want to do it repeatedly for short-lived tasks when you could instead create a pool of threads and reuse them to run several tasks. Once this purpose is clear, the notion of queuing threads becomes obviously wrong.
  • We can pass some state into the delegate used for work item queuing (or a ParameterizedThreadStart) and use that to give us some context. We need to cast that state to the relevant type before we can use it, because it’s just typed as System.Object. So far so good – except most of the time, the author ends up passing into the work item the same reference which would be available as just “this” within the method itself. So we have code such as:
loPiece.poThread = new Thread(new ParameterizedThreadStart(loPiece.ThreadMethod));

loPiece.poThread.Start(loPiece);
  • The ThreadMethod method then duly casts its parameter to its own type and uses it. All of this is pointless, as the method doesn’t need any parameters – it can just use “this” inside the method.
  • It’s very important to initialize lists with the right capacity. Again, this isn’t too bad as far as it goes – except that this micro-optimisation goes awry when he reads the TextBox.Lines property twice: once to work out the appropriate capacity and once to fill the list with initial data. Unfortunately the TextBox.Lines property has to take the existing text in the TextBox, split it (creating a bunch of substrings) and get the result into an array. This in turn means doing all the normal shenanigans associated with creating buffers which are bigger than you need, filling them, copying to a new buffer etc – exactly what we’re trying to avoid! This “optimization” will usually cost time instead of saving it. It could be easily fixed by just fetching the array in one statement, then using the same array for both the count and the list population. In fact, if you just pass the array into the List<T> constructor, it will perform the optimization for you – it can detect that it’s an ICollection<T> and use the Count property directly. Writing the simplest code actually ends up being optimal.
  • The above bullet point isn’t going to dominate the performance of that example though – there’s a potentially far worse effect due to the way the resulting “encrypted” string is broken up each time: using string concatenation in a loop. I guess we’d better hope there are no really long lines. If an author is going to give optimisation “tips” they need to be a lot more rigorous than this. Using string concatenation in a loop is probably the single best-known performance no-no in .NET. I was really shocked to see this in a book which is supposedly about making your code perform better. Now, it could be that string concatenation was used deliberately to slow things down – but in that case, why not highlight it? Drawing attention to intended optimizations gives the impression that the rest of the code is either optimized or has at least been written reasonably. If “bad” code is to be used for a specific purpose, that should be called out so that the reader won’t go onto use the same kind of code in their own production apps (which really shouldn’t be deliberately slowed down).

These aren’t the only issues I have with the code. Unicode is abused by “encrypting” text with no discussion of whether the strings he produces are valid or not (as opposed to the normal practice of only encrypting data after first converting it into binary; the encrypted binary might then be converted to text using base64 if you need to transmit the encrypted data as text). We could easily end up with strings containing surrogate high or low code points without the corresponding half in the appropriate place. When analyzing a bitmap he uses GetPixel and SetPixel for each pixel, rather than calling LockBits once and then accessing the image data in a much faster manner. (The code given does scale, but it’s not as fast as it could be. Using LockBits it would still scale, but the “per thread” work would be faster.) There are other, similar issues lurking in the text, but I’m sure you get the gist of the problem.

Conclusion

Believe it or not, there are things about this book that I actually like. It’s relatively thin, which has very tangible advantages when you’re carrying it around a lot. The sections explaining has to use Process Explorer and Task Manager to their best are useful, and the ideas of the examples are good – even though they basically cover the same ground several times. Unfortunately the bad points outweight the good far too heavily. To summarise them:

  • What I consider some of the absolute core elements of .NET multithreading (locking and monitors in particular) aren’t covered at all
  • Only the simple situation of an embarrassingly parallel algorithm is covered. In the real world developers will have to face real challenges where tasks don’t always split themselves up nicely into totally independent chunks. A reader who finishes this book assured that they are now threading gurus will face a nasty shock.
  • Server-side threading isn’t given much coverage at all, despite this being arguably the most likely environment for developers to encounter multithreading
  • The “story” element of the prose style is childish and patronising
  • The coding style, while a personal choice, makes me wince – and is particularly verbose for a book, where space is important
  • Many bad practices are encouraged, and there are plenty of important misunderstandings to trip up readers
  • The index has failed me (even when I’ve known that the subject is in the book) more times than it’s helped me

It’s a real pity. I was hoping this would be a book I could recommend to people as a precursor to reading Joe Duffy’s excellent Concurrent Programming on Windows. Instead, my current best advice is to read Joe Albahari’s threading tutorial. (I previously had a link to my own threading tutorial as well, but apparently this made people think I was fishing for more readers of that.) I’m sure there are good introductory threading books out there, but I’m afraid this isn’t one of them.

27 thoughts on “Book Review: C# 2008 and 2005 Threaded Programming: Beginner’s Guide”

  1. Hey Jon,

    I own this book you’re talking about. Are you really talking about “C# 2008 and 2005 threaded PRorgramming: Beginner0’s guide”, published by Packt Publishing… I think you are not a serious reviewer.
    I bought the book after reading another review, by Jon Mueller.
    You should check his review, because he talks about the book I bought from Amazon a few days ago. I’m following the exercises and they work fine.
    I’ve downloaded the code and it workes fine.
    I’m watching my quad-core CPU running 100% 3.5 times faster than when running the application using just one thread.
    Hey, man… You are not serious. You’ve written a fake review.
    I’ve found many wrong issues in the book. However, you are not being fair. Fair play, man. Go on writing for Manning, but don’t write fake reviews. I’ve seen your review in MSDN and I’m really angry, because I’m sure you want the people to read your threading tutorial.
    Come on, dude, nobody can believe your recommendation. You are telling us to read your threading tutorial instead of a book…..
    You should remove this review and you should write a serious review.

    Erik Thomson

    Like

  2. Excellent review.

    Another good source is Java Concurrency in Practice. Obviously the details are specific to Java, but the book covers a lot of common ground as well so C# programmers may benefit from reading it.

    Like

  3. That coding style is horrible, and the goggles, as they say, do nothing.

    It took three or four reads of that little snippet before I could understand what loPiece and poThread are.

    Waiting for a review on Concurrent Programming on Windows – you promised :)

    @Brian: “Another good source”? Did you even read the review?

    Like

  4. How can you write a whole book on threading and not spend at least 1/3 of it on locking? Obviously the author found a way to do and sneak it past his editors.

    I created some pretty impressive server side multi-threaded applications myself and I had to use locking extensively so that it would work. I cannot see how you would not cover locking concepts when discussing threaded programming. The threading portion is the easy part in my view. The difficulty is figuring out how, where, and when to lock your shared data across multiple threads.

    Like

  5. Hi Jon!

    Thanks for your review. You destroyed my book. :)
    I’m not keen on talking about reviews. However, you are seriously intentioned in destroying the book without giving the author a chance to say something about your comments.
    You didn’t send me an e-mail as you did with other reviews. You didn’t invite me to comment on your review, as you did with other authors.
    Many people wrote to my e-mail, which is public in my book (email address elided – Jon) telling me about your review. They sent me some comments. Obviously, I seems you moderated those comments and they are not here.
    I appreciate your comments. I do appreciate reviews and they help an author to improve. However, this one seems too destructive. You finish the review recommending to read a Console.Writeline based outdated threading tutorial…
    I’d love to share some of the latest parallel programming tendencies with the people that read your review. Perhaps, there is a hidden reason for doing many of the things you criticize in your review. Perhaps it is a modern beginner’s guide (beginner != expert), showing real-life examples, instead of “Console.Writeline” blogging old fashioned examples.
    Perhaps it shows simple code running in parallel. Perhaps, the author was aware of using SetPixel, because he wanted to use managed code and not faster unsafe code. Pehaps the author wanted to show something running faster. Perhaps the author wanted to concatenate strings. Perhaps the author didn’t want his book to be an OS kernel development book. Pehaps the author wanted to share some real-life multithreading experiencies and not lab experiencies. Perhaps the author thinks locks are very well explained in most C# threading chapters. Perhaps the author is involved in parallel computing since 1996, and he spent the last 13 years optimizing processes in many programming languages and he has real-life experience. Perhaps the author wrote another 42 books about computer science and electronics and he knows how modern microprocessors work.
    Why didn’t you give the author the possibility to explain to you some issues, before submitting this destructive review?
    Why did you post this review without sending an e-mail to the author? We are in Web 2.0 times.
    I think you didn’t understand who the book is written for.
    You are reviewing the book as a C# language specification. The book is intended to teach some parallel programming techniques to beginners. And, that’s explained in the book’s cover and in the book’s back.
    It could be improved. Of course, it could.
    However, the book doesn’t lye to the people.

    Thanks again. Because reviews are always welcome and I had the honor to have the book reviewed by an MVP like you.

    Feel free to drop me a few lines by e-mail.

    Cheers,

    (The author)

    Like

  6. I don’t understand, at a very basic level, how a book on threading can avoid dealing with locking, volatility, memory models, and all of the other details involved.

    I’m not looking for this book to be an UberAdvanced Joe Duffy style book, but at least explaining what locking is, and how it’s required is important.

    Like

  7. (Mailed and posted)

    I’m very surprised that you didn’t see the review before it was posted. I mailed it (in full) to Packt on March 10th, and explained that I intended to post it one week later. I made it very clear that I was happy to include comments from either yourself or Packt. I mailed it to Packt rather than directly to yourself as it was Packt who originally emailed me to ask if I’d like to the review the book – so I already had a relationship there. I had certainly expected Packt to pass the review on to you immediately for comment.

    I’d be more than happy to add your comments (highlighted in red to distinguish them from the review) at a later date, whenever you want to submit them to me. These might be just a single comment at some point in the review (either the start or end would make sense, but I don’t mind which) or as a point-by-point rebuttal where you’d like to. I promise I will not censor them at all, providing they contain nothing illegal or profane. (I’m sure they wouldn’t, but I figure it’s worth including as a disclaimer…)

    Speaking of censorship, I have certainly not censored any blog comments. I hadn’t approved Erik’s comment before you emailed me, because both his comment and yours had been trapped in my blog’s overzealous spam filter, unfortunately. I shall address Erik’s points separately.

    I won’t address each of the points in your comment separately unless you wish me to, but there are two points I *would* like to make:

    * Appealing to your authority as the author of 42 other books and your experience in the industry since 1996 doesn’t change a word of the book. A book has to stand on its own merits, not on the name of the author. I’m as happy to criticise or praise a first-time author as I am a veteran – although I’d probably cut a first-time author a little slack in terms of style. The *marketing* of a book involves the background of the author: the quality of the book itself doesn’t.

    * I wasn’t trying to review the book like a C# language specification in the slightest – but I *do* expect (or at least hope for) accuracy. I expect code to either avoid bad practices *or* explicitly draw attention to them *as* bad practices. This is the number one value for me in a book: if it’s accurate and leads me in the right direction. A book can be boring or not very good at teaching, at which point it’s a bit of a waste of time and money. When it actively espouses bad practices or make inaccurate claims beyond an inevitable small level, that’s a different matter. I felt this book felt into this category – naturally I’d expect you to disagree.

    Please let me know if you’d like a response to any other specific comments, and I hope you’ll mail me some comments to include in the review itself.

    Jon

    Like

  8. @Erik:

    This *is* a serious review. I take all reviewing seriously, which is why I’m absolutely honest in my reviews. That makes my reviews harsher than those of most people, certainly. I think many people take the attitude of “If you can’t say something nice, don’t say anything at all.” I take the attitude of “If you’re only ever going to say nice things, there’s little value in the review – it’ll never warn people of potential pitfalls.”

    Thanks for pointing out John Mueller’s review. I don’t know why I hadn’t seen it before – after writing my review I did try to find other reviews of the book, but didn’t find anything more than a few sentences. I think John’s review makes an interesting counterpoint to mine; I shall edit my review to provide a link to his, right at the top.

    Yes, the exercises will work fine, unless you’re unlucky. That’s the tricky thing about threading – aspects like the memory model often *won’t* bite very often, or they’ll affect you in hard-to-detect ways. In most areas of programming, bugs are reasonably obvious – in threading they can be very, very hard to detect. That’s why it’s so important for books on threading to be as accurate as humanly possible, and to alert readers to hidden dangers.

    As to my threading tutorial – I’d actually recommend reading Joe Albahari’s instead. If this was really an exercise in trying to get people to read my threading article, would I have stated *twice* that it’s somewhat outdated? Would you feel happier if I removed the links to my threading article completely? I doubt that would convince you that it’s not a “fake” review as you’ve claimed several times now, but if the overall consensus is that it would be the right thing to do, I’ll do it: it’s no skin off my nose.

    Now, if you want to argue with my review, please tell me which specific bits you disagree with. I’m *very* happy to debate specific points. That’s much more productive than name-calling.

    Jon

    Like

  9. @Jon:

    I wasn’t aware of your review. Thus, you didn’t receive my comments before publishing it.
    I find it really difficult to add comments and I’ll tell you why. It seems that you don’t make any difference between a beginner and an expert. You don’t seem to understand what the word “example” means. It’s an example. A short piece of the big cake. Real-life parallel programming examples are extremely difficut to prepare in a book. Sometimes, you need to make the examples simpler, because there is a limit in the number of pages. You are an author. Don’t you know that? I really can’t believe that being an author you don’t understand that simple point. I don’t want to offend you, but, some of your comments are unacceptable for an MVP like you.
    I can’t understand some of your comments. They seem to be written by a programmer that has no experience.
    The book is for developers who already know how to code using C# programming language.
    You list the topics that the book doesn’t cover… Well, I think you skipped many pages… Have you ever heard about avoiding locks? They’re talking about this technique in most current parallel programming conferences around the world.
    You talk about the examples as if they were written by a stupid. I don’t think I am a stupid person. I’m a professional and I’ve some experience about parallel programming issues. And many of them are covered in the book. It’s a book for Beginners. Therefore, its title includes the words “Beginner’s Guide”.
    It teaches difficult parallel programming issues trying to use funny examples, with some complex code combined with simple code. I cannot teach many issues in 400 pages.
    Your review doesn’t make sense. Your comments are always destroying the book. And, you are challenging the people about the points. Please, read your entire review again. Read it carefully. A 5 year old child will discover that you are hating the book in every sentence.
    How can I send you comments when I feel that you are hating the book?
    I’ve never seen a review like yours in my hole life. You have the right to post this review. You have the right to say that buying my book is wasting money.
    Do you think that it makes sense to add a comment for each of your points, explaining that you didn’t understand A, you didn’t understand example B, you didn’t understand example C. Is that possible?
    I believe you hate my book and there is nothing I can do to avoid your harmful comments.
    I’ll post comments. OK. I’m sure you’ll have more harmful comments. You seem too rude in many answers to some posts. I don’t like that style and I don’t want to be part of this horrible game.
    I think that you believe you are a C# super star. I am not a C# super star. I am a professional who tried to write a nice book with some examples showing specific situations. That’s the book. A small piece of the great cake.
    I’ll send you my comments next week. The only think I’ll ask you is a little respect. I am a professional, not as brilliant as you are, but I am a professional. I can be wrong, but I don’t like rude comments. That’s not my style.
    You are talking everywhere that my book is wrong about nearly everything. I’ll prepare all the information for the people who reads this review, because it is really lying the blog readers, and it is published in MSDN.

    I’ll leave you just one question. Are you sure that some Console.Writeline threading posts are more interesting than the whole book? Are you sure that the book is completely unaccurate? Are you sure that one of the problems is using SetPixel for the example in which an application runs 4 times faster in a quad-core CPU? Did you test the applications included? Did you benchmark the results in multicore or multiprocessor systems? Are you really sure that the book is useless as you say? You can’t be serious. :)
    Nonetheless, again, I appreciate your review. I’m sure that many people who reads this review and then downloads the code samples and reads the table of

    Like

  10. @Jon:

    I disagree with some points of your review
    “Fairly disastrous advice (IMO) about both I/O and the GC”
    Did you test the examples in quad-core servers? They are pretty scalable…

    “Using Control.Invoke/BeginInvoke to update the UI (although this comes very late in the book – chapter 10 out of 12)”
    I found the best example about this topic in the book

    “Noting that sharing data between threads is difficult – but coming to the wrong conclusions (more later)”
    The author avoids locks, and talks about locks many times, I’m an average C# programmer. His code works. I don0’t wanna write an OS kernel, as the author says in his comment

    Exception “handling” (where “swallowing exceptions and just reporting them with Debug.Print” counts as “handling” apparently)
    I’ve learned exception handling in a C# programming book. I don’t think it should be included as a great topic in a parallel programming book

    Parallel Extensions from .NET 4.0, with both PLINQ and TPL
    Nice to find some information about future .Net in the book… Don’t you think so? I haven’t found comments about that in your review :(

    “I find it absolutely incredible that a book on multi-threading in C# doesn’t even mention the “lock” keyword.”
    Are you joking???? Jon, Read the book again, be serious as another comment says.

    “Okay, it’s nice to be able to split tasks up completely independently where possible, but in the real world you sometimes have to use shared mutable state (or at least, it’s often the simplest approach).”
    I believe the book is a nice introduction to parallel programming. Don’t you think so? No, you don’t, you think the book is horrible…. mmmm Maning, Maning Parallel Programming……

    “When I first got the book, I looked up several entries in the index to see how they’d be handled. I was shocked to find that none of these have an index entry: BeginInvoke or Invoke”
    Contradictory……. Previously, you said: “Using Control.Invoke/BeginInvoke to update the UI (although this comes very late in the book – chapter 10 out of 12)”…. mmmm Maning, Maning Parallel Programming……

    “The concept of accessing state from multiple threads is glossed over for the entirety of the book. Basically whenever multiple threads want to make their results available, they put them in different elements of an array or list. There’s an assumption that if you read from that array/list in a different thread, it’s all okay. Likewise there’s an assumption that it’s appropriate to read integer variables written to in one thread from another thread without any locking, volatility or use of the Interlocked class. I’ll come back to this topic when I tackle accuracy later on.”
    The examples work fine and they scale in multicore CPUs. I’ve seen my Core i7 running with 8 threads, 5.8 times faster than the single threaded version…

    “It’s tricky with technical books: non-technical editors have good reason to be wary of going too far, as small changes in wording can have make a large difference semantically, but it does make a big difference to a book’s readability when the language is clear and idiomatic.”
    I understood everything explained in the book. Cool samples… NASA’S CIO hiring you…… Cool! :)
    You hate For Dummies. Don’t you?

    “It’s not my preferred style to start with (particularly focusing on large GUIs instead of short, complete console apps) but I rarely felt particularly lost in the listings – there was usually enough context to hold onto. Here, I feel there’s very little context at all. If you accidentally miss out a step, you’ll have a really hard time working out which one it is or what’s wrong.”
    Do you love console applications? WE DON’T!!!!! WE HATE THEM! Average C# programmers hate console examples. I loved the samples in the book. Great examples that really work. What else does an average C# programmer want from a book like this one?

    “We are told of FBI agents getting us capuccinos, the NASA CIO wanting you to use the Paralle

    Like

  11. Roy and the author: I’m afraid your comments have been truncated. I’ll reply to the bits I can see :)
    (I may need to post this reply in multiple comments for the same reason.)

    Roy first:

    “Fairly disastrous advice (IMO) about both I/O and the GC”
    Did you test the examples in quad-core servers? They are pretty scalable…

    Have you profiled them vs using a streaming model? What happens if you give it several very large files at the same time? It will try to load all of 4 files immediately – which not only wastes memory, but

    “Using Control.Invoke/BeginInvoke to update the UI (although this comes very late in the book – chapter 10 out of 12)”
    I found the best example about this topic in the author’s book

    I was mostly surprised it was so late. It’s a pretty basic operation for user interfaces, and yet it comes after managing thread pool threads and other much more detailed bits.

    “Noting that sharing data between threads is difficult – but coming to the wrong conclusions (more later)”

    The author avoids locks, and talks about locks many times, I’m an average C# programmer.

    The problem is that the author gives the impression that you can tackle most problems without locks. That’s simply not true in my experience. In the real world, it’s very, very hard to get away without locking – or at least to do so safely. Ignoring locking doesn’t make it (or its importance) go away.

    His code works. I don0’t wanna write an OS kernel, as the author says in his comment

    His code works if you’re not unlucky with the memory model. It’s not thread-safe though. For instance, he reads integers written in one thread from another thread: there’s no guarantee that the reading thread will ever see the new value, unless you have some sort of memory barrier. These are subtle issues which I don’t expect to be fully covered in a beginner’s text, but I do expect at least some sort of warning, preferably along with safe code. (For many of the examples, simply making the variable volatile would have sufficed.)

    Exception “handling” (where “swallowing exceptions and just reporting them with Debug.Print” counts as “handling”
    apparently)

    I’ve learned exception handling in a C# programming book. I don’t think it should be included
    as a great topic in a parallel programming book

    I don’t believe it should be covered in great detail – but I don’t believe a beginner should be left with the impression that writing a line to the console should count as “handling” exceptions. Just a single paragraph explaining that error handling will vary by application, and that you need to carefully consider what to do (based on the fact that that thread’s task has failed) would have sufficed. Instead, we are left with the impression that it’s perfectly fine to just write to the console and effectively ignore the problem.

    Parallel Extensions from .NET 4.0, with both PLINQ and TPL
    Nice to find some information about future .Net in the book… Don’t you think so? I haven’t
    found comments about that in your review :(

    Yes, I think it’s nice that it’s included – although I would rather have seen that space used for describing locking. I would prefer that beginners understand the basics before being taken through more advanced technologies like Parallel Extensions. However, I do mention that it’s covered in the book. In my list of topics covered:

    “Parallel Extensions from .NET 4.0, with both PLINQ and TPL”

    “I find it absolutely incredible that a book on multi-threading in C# doesn’t even mention the “lock” keyword.”
    Are you joking???? Jon, Read the book again, be serious as another comment says.

    Could you point to exactly where the “lock” keyword (as opposed to locking in a general fashion) is mentioned?

    “Okay, it’s nice to be able to split tasks up completely independently where possible,
    but in the real world you sometimes have to use shared mutable state (or at least,
    it’s often the simplest approach).”

    I believe the book is a nice introduction to parallel programming. Don’t you
    think so? No, you don’t, you think the book is horrible….
    mmmm Maning, Maning Parallel Programming……

    No, I don’t think it’s a nice introduction to parallel programming, because of the impressions it leaves: that you can do everything without locking, and that locking is something only hardcore developers would use.

    “When I first got the book, I looked up several entries in the index to see how they’d be handled. I was shocked to find
    that none of these have an index entry: BeginInvoke or Invoke”

    Contradictory……. Previously, you said: “Using Control.Invoke/BeginInvoke to update the UI (although this comes very
    late in the book – chapter 10 out of 12)”…. mmmm Maning, Maning Parallel Programming……

    I don’t see what’s contradictory about that at all. They appear in chapter 10, but not in the index. Are you claiming that any of those index entries do exist? You know, in the index?

    “The concept of accessing state from multiple threads is glossed over for the entirety of the book.
    Basically whenever multiple threads want to make their results available, they put them in
    different elements of an array or list. There’s an assumption that if you read from that array/
    list in a different thread, it’s all okay. Likewise there’s an assumption that it’s appropriate
    to read integer variables written to in one thread from another thread without any locking,
    volatility or use of the Interlocked class. I’ll come back to this topic when I tackle accuracy later on.”

    The examples work fine and they scale in multicore CPUs. I’ve seen my Core i7 running with
    8 threads, 5.8 times faster than the single threaded version…

    Yes, the examples scale – they just might not report the right results all the time, due to subtle memory model issues. The UI thread might continuously read the wrong value.

    Correctness in parallel programming can be very tricky. The very fact that you think incorrect code works fine demonstrates this.

    “It’s tricky with technical books: non-technical editors have good reason to be wary of going
    too far, as small changes in wording can have make a large difference semantically, but it
    does make a big difference to a book’s readability when the language is clear and idiomatic.”

    I understood everything explained in the book. Cool samples… NASA’S CIO hiring you…… Cool! :)

    You hate For Dummies. Don’t you?

    I’ve never read any “For Dummies” books. I’ve read Head First C#, where I didn’t like the style, but it was handled better than here. Really, I found the whole tone hugely patronising. It’s quite possible to make technical books “fun” without being patronising.

    Like

  12. (Looks like my comments aren’t being truncated. No idea why – please accept my assurances that this is not some deliberate scheme on my part. Mailed and posted, with an extra paragraph or two in what I’m mailing.)
    Moving on to the author’s comments so far:

    I wasn’t aware of your review. Thus, you didn’t receive my comments before publishing it.
    Absolutely – and I’m still very surprised that my review wasn’t passed on to you. I’ll learn from this, however, and always make sure I send a copy to authors as well as to the publisher if I’m mostly talking to the publisher. Very strange. Anyway, moving on.
    I find it really difficult to add comments and I’ll tell you why. It seems that you don’t make any difference between a beginner and an expert. You don’t seem to understand what the word “example” means. It’s an example. A short piece of the big cake. Real-life parallel programming examples are extremely difficut to prepare in a book. Sometimes, you need to make the examples simpler, because there is a limit in the number of pages. You are an author. Don’t you know that? I really can’t believe that being an author you don’t understand that simple point. I don’t want to offend you, but, some of your comments are unacceptable for an MVP like you.
    Yes, I totally understand that often examples have to be simplified. However, when they are simplified to the extent that they are dangerous (e.g. changing STAThread to MTAThread) I believe that either the examples need to be changed or the dangerous practice needs to be called out in the text. Would you use MTAThread for a production Windows Forms application? I’d be surprised if that were the case – but you’re happy to change STAThread to MTAThread in examples with no mention of the fact that this flies in the face of best practices.
    I can’t understand some of your comments. They seem to be written by a programmer that has no experience.
    Does this come under the heading of not wishing to offend me? :)
    The book is for developers who already know how to code using C# programming language.
    Including locking or not? If I were writing a beginners’ book about threading, I wouldn’t assume they understood the “lock” keyword. I would definitely talk about locking very explicitly.
    You list the topics that the book doesn’t cover… Well, I think you skipped many pages… Have you ever heard about avoiding locks? They’re talking about this technique in most current parallel programming conferences around the world.
    Yes – and you know why that’s part of cutting edge parallelism? Because it’s hard. Yes, it scales better – but it’s hard. As you keep saying, this book is for beginners. I would rather teach beginners techniques which may not (scratch that – definitely don’t) scale as well as lock-free programming, but which gives them safe code. Furthermore, those safe techniques also allow you to tackle problems which are nigh-on impossible to tackle in a lock-free way. No, I’m not talking about kernel development – I’m talking about the kind of problems real C# developers face in the real world, where understanding locking is crucial.
    If I were hiring a C# developer and they claimed to have knowledge of multi-threading, I would certainly expect them to understand locking. Wouldn’t you?
    You talk about the examples as if they were written by a stupid. I don’t think I am a stupid person. I’m a professional and I’ve some experience about parallel programming issues. And many of them are covered in the book. It’s a book for Beginners. Therefore, its title includes the words “Beginner’s Guide”.
    As I’ve said several times now, I judge a book solely on its text. I have no real grounds to judge whet

    Like

  13. I guess this is one of those times when, with 20:20 hindsight, a “cc” could have saved a lot of pain. From an external viewpoint, I would personally place fault here at the publisher for not forwarding the review (that had been requested) in a prompt manner.
    For a bit of balance, I personally don’t find the review unprofessional or unacceptable – it comments squarely on technical points that are well-qualified and explained – it isn’t just “hate it”.
    Personally, I’m all for honest reviews; that means picking up on the bad as well as the good. Maybe a bit more of the “good” could have been highlit (as balance).

    Like

  14. (Oh the irony – a comment saying that my comments aren’t being truncated is, in turn, truncated! For the first time ever, my own comment made it into the spam bin. Odd. Annoyingly, that meant it *wasn’t* mailed. If only I’d mailed it first, I’d have a record. Oh well.)

    I’m not going to go back and rewrite the comments for everything else, just a few quick points:

    – No, I don’t think that *everything* in the book is wrong. However, I think enough is wrong to give readers dangerous impressions. I believe that someone reading this book and believing it all to be accurate will probably go on to write inaccurate code, which may well not fail *obviously*, but is incorrect nonetheless. Parallel programming is very subtle, and diagnosing or even *noticing* problems can be very hard. You say that my review is “lying” – I hope that either your comments will justify that assertion, or you’ll retract it. “Lying” is a very strong term in my view. I haven’t written anything in the review which I know to be false. However, I will edit the review to add something at the top to the effect that I’m *not* claiming everything in the book is wrong.

    – There has been a lot of talk in comments here and elsewhere about the *people* involved. I don’t like to make reviews about *people*. If there are any ad hominem comments in the review, please (anyone!) point them out and I’ll remove them. I apologise in advance for any such comments which are found. The important thing is the text of the book, not the people involved. It doesn’t matter whether I’m a C# “super star” or not (I’m really not – see Eric Lippert if you want to talk to a real C# genius). It doesn’t matter whether the author has written a million correct parallel programs which have revolutionised the industry. It doesn’t matter how many other books have been written by the author, or how well they’ve been received. None of that changes the text of the book, or its accuracy. Those are surely the important things from a reader’s point of view. The one aspect which *is* about people is in judging style. This is clearly very subjective. I *hope* I’ve made it clear in the review which aspects are subjective rather than technical. Again, any corrections or clarifications are welcome.

    Please – and I say this to those who love my review and those who hate it; those who love the book and those who don’t – let’s keep the discussion *technical* wherever possible. There may still be room for debate (is it acceptable to use MTA for WinForms applications or not? I think not, the book says it is, let’s debate that) but at least there can be *evidence*.

    Right – I’m copying this text for safety and then keeping my fingers crossed it gets posted properly,
    Jon

    Like

  15. One point that has been made about the review being “published” on MSDN: I genuinely wasn’t aware that the link would appear there.

    Normally if I want a blog post to end up on the MSDN C# page, I use the CSharpDev and CSharpDevCenter tags (there are two due to a muddle when setting them up, unfortunately). I deliberately *didn’t* use them here. I suspect that part of the MSDN site just grabs all C# MVP blog posts.

    Also note that I *won’t* be submitting an Amazon review. If you have the book and like it, maybe you should submit a review there? (Currently there aren’t any, although that doesn’t mean that none has been submitted – they can take a while to come through.)

    Jon

    Like

  16. As someone who hasn’t read the book, only this discussion, but has written a fair amount of multi-threaded code (though mainly in C and Java):

    Jon’s review strikes me as well-written, with good, *technical* points; points which, even without having any C# experience, make excellent sense to me. A book that talks about parallel programming but glosses over synchronization and communication between threads seems to me to be a book I would recommend _against_, since those are precisely the kinds of areas where a beginner would need advice.

    On the subject of keeping examples simple, that is of course a necessity – but when an example is simplified enough so as to have to elide something that is normally important to include, that omission should be mentioned. After all, beginners *will* take your code verbatim, copy it into their project, and modify it just enough to adapt it to their problem! If there are any important parts missing from the example, they will also be missing from the copied-and-pasted code in the reader’s project. If you at least *mention* where there *are* bits missing, then the reader has that to tell them where they need to fill in bits (possibly from other examples, which you can of course refer to).

    Also, if the book is billed as “Where you are a beginner to working with threads or an old hand who is looking for a reference, this book should be on your desk”, I would expect that it should at least have references from the index to the pertinent parts of the book, for things such as synchronization primitives (Monitor?), memory model and similar.

    The author also seems to be of the opinion that a console-based example is somehow inferior to a GUI-based one; but if you’re trying to show the fundamentals of parallel programming, that can in fact be done very well using as simple a UI as possible, and frequently, that is a console-based one. Certainly, running a GUI asynchronously from computation and such is one area where parallelism is highly useful, and such areas should *also* be covered, but for introductory examples at least, using something simpler such as console for the UI actually makes the entire example simpler, removes boilerplate, and actually allows the author to focus on the meat of the problem at hand!

    All in all, there are different ways to react to a negative review – one is the constructive route, where feedback is taken in, technical points addressed, and so on. The main bulk ‘responses’ to this review have plainly failed to do any of those, and that is at least as disappointing as the issues in the book itself.

    // Christian

    Like

  17. I think what Skeet does is being honest with himself and his blog readers. People like him have to be honest and accurate, because others will make decision that waste time and money – first one the most important- according to what they are saying. So please Jon do what you should as usual.
    To authors who decide to write a book, it’s fairly simple; let what you write speaks about what you know and how deep you know it. The equation is very simple: GOOD BOOK == POSITIVE REVIEW

    Like

  18. This review was harsh, but deservedly so. I’m sorry (name elided) but saying that a lock-free approach is the ultimate in multi-threading is one thing, but it’s black magic to do properly and having several threads accessing some shared state without any synchronization mechanism is definitely not the way to do it properly. Oh it will be fast. It also will be disastrous along the way. “lock-free” does not mean “let’s have everything mutable and never ever write lock in the code”

    I think concurrency programming can be taught without dropping a 2 kilograms Joe Duffy Bible on the head of the poor unsuspecting beginner, but it doesn’t mean teaching them to shoot herself in the foot in a parallel way.

    Besides, I’d like to salute the unshakable civility of Jon Skeet regarding the barrage of eerily similar comments from disgruntled reviewees/readers/both.

    Like

  19. One thing that should be mentioned to all those who ran the examples and didn’t encounter any problems: just because you didn’t encounter them, doesn’t mean they’re not there. *In particular* with things like parallelism and synchronization, issues can very much depend on the precise machine you’re using – so that something that runs fine on one type of machine will crash, or just produce slightly incorrect results, on another.

    If you write simplified examples where you have taken short cuts or otherwise are doing something that will work in the specific example but might not be a good idea in general, then you as the author *need to point that out*. Otherwise, readers, especially beginners, will pick up an reuse the *entire* example, *including* the parts that are good in the example but bad in the general case.

    The end result is that all these people who have learned through that book will have gotten used to doing things the way the book says, and won’t have any idea about the pitfalls they will encounter when the code from the book’s examples *does* encounter circumstances where the short cuts don’t work.

    All of this can of course be avoided by simply noting *explicitly* along with each example which parts are the important bits, and which parts are abbreviated / simplified and need more attention if the code is copied-and-pasted into real-world usage.

    A common example of this kind of thing is error handling. For the purpose of example code, it is often very convenient to simply not even check for certain errors, because you know that within the context of the example, those won’t actually occur. But such example code should still come with a notice saying “of course in production code, we would have to check for and handle any errors we might encounter, but here we’re ignoring them for simplicity’s sake” – this could be a footnote, even, so doesn’t need to detract from the flow of the code or its accompanying text, just as long as it is clearly there.

    Best wishes,

    // Christian

    Like

  20. @Jon, you say “(Oh the irony – a comment saying that my comments aren’t being truncated is, in turn, truncated!”

    I didn’t write the multithreaded code for Community Server…… :)

    Just a bit of humour.

    I’ve done my best to explain a very difficult topic in less than 400 pages, following the Beginner’s guide series guidelines. I guess I failed, but I’ll offer my comments to some important issues pointed by Jon.

    I’m always willing to improve my writing and my knowledge about topics. Teaching a difficult topic in less than 400 pages using huomour, real-life examples and funny situations (that’s the Beginner’s Guide goal) is a difficult task. I tried to do it.

    Believe me, it is easier to write a 1,500 pages book than writing a 388 pages book about parallel programming.

    See you next week with my comments.

    Best wishes,

    (The author)

    Like

  21. (Mailed and posted)

    @Author:

    About community server: indeed :) Ironically, one thing I’d like to see is threaded discussions. A completely different kind of threading question, of course :) (Actually, I’ve been wondering about using 20% time to work out new visualisations of threaded discussions, but anyway…)

    I quite agree that when you don’t have the luxury of explaining everything, one of the tricky things is working out what to include and what to leave out. I think we disagree about where beginners should start with threading :)

    I’ll look forward to including your comments in the review – have a good weekend.

    Jon

    Like

  22. Wow, maybe I don’t understand because I’m not an author but this review was taken waaaay too personally.

    In all parts of the review Jon very carefully stated exactly why he had taken issue. He also clearly stated when he was just giving his opinion.

    If a person writes a technical book then they should expect to be reviewed. Reviewers have the obligation to be honest and say it as they see it. They also have an obligation to state when it is their opinion or subjective which Jon did on numerous occasions.

    An appropriate response from the author would have been rational rebuttal in detail answering point by point Jon’s issues. That would have earned respect.

    Jon is a highly visible and very well respected member of the .NET community. He is a mega-contributer and to suggest he was “hating” and “plugging” is quite frankly ludicrous. Just see StackOverflow.com for proof of his tireless dedication to the community.

    One final point: The fact that it is a beginners book does not invalidate any of Jon’s points. Jon raised serious concerns about important best practice issues.

    I am a potential reader of that book. I am a beginner to intermediate and I have one pet hate; being half-taught potentially dangerous practices with no warning or context information. Thankfully, I read around a lot so I won’t get burned by a single book but it is scary how much damage could be inflicted.

    Just because I am not an uber-developer does not mean I do not want a solid understanding of critical issues.

    Like

  23. Just to mirror a note the author left on another forum where I was being criticised personally: let’s keep this about the technical side. Just as there’s no need (IMO) to criticise me for writing an honest but harsh review, there’s no need to criticise the author personally.

    I’m looking forward to his rebuttal/acceptance/discussion of various points of my review – it takes time to write such things carefully, and I appreciate him doing it.

    I’m not criticising J Milne’s comments here, although as an author I can understand very well why the author took it personally. Books take a huge amount of time and devotion – they’re labours of love. Just because I don’t like a book doesn’t mean I don’t sympathise with the author for having to read a review like this. I haven’t had such a review myself, and I have no idea how I’d react to it. I hope I’ll never find out.

    Anyway, let’s wait for the response.

    Jon

    Like

  24. First of all, I found the review to be frank, professional, and appropriate for a technical book, and not a personal attack. I can understand how the author could take offense, as no one likes to have their work criticized. This is especially true since he apparently felt blind-sided due to an unfortunate miscommunication. However, I can’t see how anyone else can fault Jon’s approach.

    I am of the opinion that accuracy is the single most important factor in any technical book, regardless of its intended audience. In fact, as Jon has commented in some of his previous reviews, accuracy can be even more important in a beginner’s book, because a beginner does not have the experience to be able to discern accuracy from inaccuracy. What good is it to introduce a programmer to multithreading if, at the same time, you are leading them astray on issues like garbage collection and exception handling? It is an author’s duty to illustrate best practices in all aspects of his discussion, whether they specifically fall under the topic of the book or not.

    I think it should also be pointed out that, while the author was trying to write a “Beginner’s Guide” to multithreading, multithreading is not a beginner’s topic. Even the simplest of multithreading problems requires a solid understanding of programming principles. In my opinion, it is not sufficient to introduce a few concepts and assume that the reader will pick up the rest later. Multithreading can have terrible consequences when not done correctly, and no one should be encouraging beginners to try it after only a simple introduction to the topic.

    Like

  25. First off, I want to say that David Nelson has pretty much summarized my attitude quite well. Except that I don’t see the problem with having a beginner’s guide to an advanced topic. As they say, everyone has a first time for everything. And the author did acknowledge that he expects his readers to be quite experienced C# programmers, only new to threading (maybe he should also consider those developers skilled at threading and wanting to port their skills to C#).

    Yann Schwartz makes a very good point about the irrational comments defending the book. When I read those (not the ones by the author, there’s a difference), the only thing I could think of was “this guy is working for the publisher”. Either that or incredibly uninformed. Since they wrote these comments allegedly after reading the book, the only thing I can conclude is that the book completely failed to emphasize that multithreaded programs are not deterministic, and bugs can manifest at any time, generally via “action at a distance”. By that I mean a change was made in a portion of the application completely unrelated to the buggy section, but perhaps it caused the task not to complete in a single quantum and therefore a race condition was exposed. Thankfully multicore bring race conditions to light a lot more often, but the important message is “You can’t test quality into multithreaded code.” And apparently the book didn’t get that point across. I have to wonder if the author even tried.

    As for the author, from his response to the review I have to say he’s a menace to society as long as he’s writing code. Yes there are interesting problems which require concatenating strings. But there are none which require String.Concat (or string operator+) in loops, which clearly is what Jon was picking on. No C# programmer who doesn’t know elementary performance tidbits like that should even think about writing a book on using threads to improve performance.

    Like

  26. >but in the real world you sometimes have to use >shared mutable state (or at least, it’s often >the simplest approach).

    Erlang appears to get by without shared mutable state reasonably well. It is fairly real world too.

    Like

  27. @Paul: Yes, if you’re using a language *designed* around not sharing state, you’re clearly in a better position to do without. In C# it takes significantly more effort.

    Like

Leave a comment