Posts

Showing posts with the label Synchronization

Threading with .NET ThreadPool Part 4

Suppose you've been given the task to write a function that copies the contents of one folder to another. So you set off on your merry way and come up with something like the following. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ThreadPoolPart4 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // Get the Folder names, copy contents from one to the other FolderBrowserDialog fb = new FolderBrowserDialog(); fb.ShowDialog(); string src = fb.SelectedPath; fb.ShowDialog(); string dst = fb.SelectedPath; // no error checking on the names, this is an example only if (dst != src)...

Threading with .NET ThreadPool Part 3

To wrap up this series of articles, I am going to make the application we've been working on do something a little more interesting. If you will recall in my first article on the subject of ThreadPool , I go over several ways to call the primary thread pool function QueueUserWorkItem and demonstrate how simple it is to multi-thread an application. In my second article, I look at a skeletal application that doesn't really do anything; it just displays messages on the console. However, and more importantly, it demonstrates some of the aspects of synchronization. You must synchronize if you are to do anything of real consequence with threads. So, what sort of interesting things will this application do? My application will paint a pop-art picture. Actually, it will place random pixels on a PictureBox. Okay, its not that useful (or argueably that interesting), but it will demonstrate a means by which threads report progress to the GUI thread. Let's look at the work it...

Threading with .NET ThreadPool Part 2

Let's continue looking at System.Threading.ThreadPool . In the last article , we went over some of the basic features a thread pool should have. We looked specifically at System.Threading.ThreadPool to see how to get your App threading quickly. And, we touched on some aspects missing from Microsoft's thread pool implementation that are needed for an "industrial strength" application. So today, we will examine some of those missing features. Let's start with a skeleton application. This application starts a master work item that is responsible for feeding service work items to the thread pool. The service work items do some work (right now, they display a message with Console.WriteLine(...) and then sleep a random amount of time in the sub-second range). We get a taste of synchronization with the shared random number generator where I surround it with a lock(...){ } statement to make it thread safe. When service work items are done, they exit. "Ex...

Thread Synchronized Queing

Today's topic gets back to some multi-threading. I find it very useful to have threads pull work from a queue and have one master assignment manager feed the queue. However the standard System.Collections.Generic.Queue is a little inadequate for me because it is not fully thread-safe. I found it a little disheartening that the Queue class members are not overridable either. So we write our own, here are my requirements... The queue must synchronize multiple writer threads writing elements to the queue. The queue must synchronize multiple reader threads reading from the queue. If there is nothing in the queue, a reader thread must wait for something or timeout. Those waiting on the queue can be “interrupted”. Of course, no two readers will ever get the same element off the queue. So let's start coding... I start with a new class called SyncQueue in my own name space and I will make it generic. namespace QueueExample { public class SyncQueue { public void Enqueue(T element)...

Locking Guidelines

In my last post ( Lock Up Unlocked ), I gave you some basic guidelines for locking resources in multi-threaded programs. Basic guidelines for locking. Avoid simultaneously locking multiple shared resources in a single thread. If multiple shared resources must be locked simultaneously, endeavor that all threads lock the resources in the same order and unlock them in reverse order. If they can't be unlocked in reverse order, then endeavor to unlock in the same order and do not lock an earlier resource till all later locks are released. If you can't follow these guidelines, then timeout. In today's post, I am going to elaborate a little on each principle. But first, let's discuss "resources". Many of you can quickly name the commonly understood resources. Things like memory, cpu, network jump right out, but that's because we are so used to looking at Task Manager and Resource Monitor. Besides, they are a little esoteric, programmers are concerned about sp...

Lock Up Unlocked

In my last post ( Locked Up! ), I gave an example of a simple deadlocking application. If you run it and click the button a few times rapidly, the application stops responding. Then, if you pause the program and examine the stack trace of each thread, you find the GUI thread waiting for the lock, and the child thread waiting for Invoke() to return. The child thread is holding the lock, so the application is deadlocked. This is also known as a "deadly embrace". So, I affectionately referred to the two resources as Resource RA and Resource RB and asked you to identify them in the program. One of the resources is pretty obvious. That would be the lblResult.Text . It doesn't matter whether you call this RA or RB, so I'll call it Resource RA. Regardless, for some odd reason, the programmer has decided that the lblResult.Text property needs to be protected from simultaneous read and write. This protection is not really necessary, but pretend for a moment a valid s...

Locked Up!

Today's example is NOT useful code. Instead, it's a simple example of a bad practice in multi-threaded code floating around out there in programming land. This example is C# specific, but the concepts apply to other languages as well. Since this is a bad example, I'll start off by telling you why its bad. The application locks then blocks on another resource. It's as simple as that. Many of you understand that if Thread A locks Resource RA and tries to lock Resource RB, while Thread B locks Resource RB and then tries to lock Resource RA, you have a classic "deadlock". The following code "deadlocks". Run it and click the button a few times and it will deadlock. So, the real question is not "why is it deadlocking?" I just told you up front, it's a classic deadlock. The real question is "what are the equivalents in this program of Resources RA and RB?" To answer this question, you can run the program in your favorite de...