William さんのプロフィール.Net Zoneブログリスト ツール ヘルプ
5月6日

Generic CountdownLatch Synchronization Primitive

The CountdownLatch can be a very useful synchronization primitive for certain threading jobs. Here is my generic version that calls a generic Action<T> after latch reaches zero.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace WJS.Threading
{
    /// <summary>
    /// CountdownLatch is a very fast and thin one-time latch that counts down from "count".
    /// Calling Signal from any thread will atomically decrement the count.
    /// When count reaches zero, the passed delegate is called on the calling thread passing optional state.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CountdownLatch<T>
    {
        private int remain;
        private Action<T> action;
        private T state;

        public CountdownLatch(int count, T state, Action<T> action)
        {
            if (count < 1)
                throw new ArgumentOutOfRangeException("count");
            if (action == null)
                throw new ArgumentNullException("action");
            this.remain = count;
            this.action = action;
            this.state = state;
        }

        /// <summary>
        /// Gets the latch remaining count. If remaining is less than or equal to zero, the latch was opened.
        /// </summary>
        public int Remaining
        {
            get { return remain; }
        }

        /// <summary>
        /// Decrement the count by 1 and call action if count is zero.
        /// </summary>
        public void Signal()
        {
            // The last thread to signal, runs the delegate.
            if (Interlocked.Decrement(ref remain) == 0)
                action(state);
        }

        [Conditional("DEBUG")]
        public static void Test()
        {
            CountdownLatch<string> cLatch = new CountdownLatch<string>(5, "Hello",
                delegate(string s)
                {
                    Console.WriteLine(s);
                });

            for (int i = 0; i < 10; i++)
                cLatch.Signal();
            Console.WriteLine("Done");
        }
    }
}

Use Win Form in a VS Team Test library

 

This may be common knowledge, but I just discovered it. Test projects in VS Team Test are class libraries. Normally you write tests like a console app, with no UI. You just test api results and test results with the Assert class – nice, simple and works great. However, a lot of times, I like testing and modeling work in progress with a UI form. I just add a bunch of buttons each with some code I am testing. Works good for me as it is visually organized and double-click to see code-behind is just so natural. I use a form as a kind of scratch pad for ideas and small tests on logic. Not as a replacement for unit tests, but as dev tool. Also a nice way to create various samples for using your library. Nuf said. Anyway, I thought it would be nice to pop a form up as one of the unit tests and work with it. Kinda like a manual test. This is nice because you don't need to create yet another Project just to create Windows Form test harness and junk up your dir structure. So to keep your forms and helper class in the Test project library. Here is sort summary:

  1. Create a Windows form in the project as normal. This will add the System.Windows.Forms reference for you.
  2. Open your blank form and add buttons and logic as needed.
  3. Add a new "Unit Test" to the project and pick a good name.
  4. Add a [TestMethod] method to the class and call it something like TestForm1. This is the unit test method that will be called via testing framework. Add code to open your form in this method; something like:

    [TestMethod]

public void TestMethod1()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new Form1());

 

////Microsoft.VisualStudio.TestTools.UnitTesting

//Form1 f1 = new Form1();

//f1.ShowDialog();

}

    You can either use the Application.Run method or just use ShowDialog() as shown.

  1. Run your "TestForm1" unit test. It will bring up your form. You can click and test your form as needed. All Console.WriteLine() output will be collected into the Test Result for the unit test. You will see it only after you close the form. Any uncaught exception will also be posted in the test output record. This makes it nice and tidy.
  2. When you close your form, your other selected tests (if any) will continue. Perfect!

Add as many forms or classes as you need. Using this method, you can collect all your samples into the same test project and distro a single library along with your other project you are testing.