Best practices and principles aren't rules. They're guides to the judgement of the programmer. Sometimes we forget that.
When you need to share a list of specific information between asynchronous processes, you probably need the ConcurrentDictionary. Except, of course, when you don't.
When it's important to know what path your application took when processing data, a log of that path can be helpful. And, when you need to make a decision in your code based on an earlier decision, that internal path can make your code both simpler and easier to understand.
If you're creating an asynchronous application (and you should be) you'll be glad to know that .NET offers ways to share data that don't require you to lock up your application.
The basic functionality of the BlockingCollection makes creating asynchronous applications easy to do. But you need to use some of the BlockingCollection's other tools to create applications that handle typical real-world problems.
Dividing your application up into simple processes will make it easier to maintain and extend. Using BlockingCollection to communicate between those processes will let you make those processes run asynchronously.
With the right tools, creating an asynchronous application can give you not only a more responsive application that makes better use of your multi-core computer, it can also make your application simpler. Really, asynchronous applications should be your default choice.
You want to give the user the ability to select one (or more) items from a table. It's not as easy in ASP.NET MVC as you might like... but it's not awful, either.
If you have software development skills then there are actually a wide range of positions you can reasonably expect to migrate to (assuming you want one of those jobs). Here are some useful numbers on average salaries and job openings on which to base your decision.
Developers (including you) benefit when you provide a string representation of your class. By implementing IFormattable, you can take control of this representation and provide some flexibility. Besides, if you don't provide one, the Microsoft .NET Framework will provide a useless one for you.
When you need to know when a file or folder appears, disappears or is renamed -- in fact, if almost anything at all happens in the file system -- you can have Windows notify your application so that you can take action.
There are lots of benefits to gathering information by opening a dialog box instead of sending your user to another page. Fortunately, jQuery and ASP.NET MVC make it easy to do (and you don't have to worry about offending pop-up blockers).
If you need to have objects look alike but don't have any code to share, you don't need inheritance -- you need an interface. Here's an example of how interfaces provide a more flexible way to deal with similar-but-different classes.
You want to use a DLL in multiple projects (it's even possible that other developers at your company might find your DLL helpful). The easiest way to distribute and deploy that DLL, or any other combination of files, is with NuGet. Really.
You can dramatically simplify your code by using classes to define read-only/immutable objects … but to create classes that behave correctly requires a little bit of redirection.