Monday, June 28, 2010

Simplest thread-safe way to set BindingSource's DataSource

// Fire and forget threading. Even the WCF took a long time, 
// your UI won't be locked(the dreaded white window with Not Responding on title bar)
ThreadPool.QueueUserWorkItem(o => 
{                
    var tx = new TheServiceReference.ServiceClient();
    var sh = tx.Sales_OpenByOrNum("aaa");
    // using the this.Invoke will make the BindingSource run on UI thread
    this.Invoke((MethodInvoker)delegate
    {
        bdsHeader.DataSource = sh; 
    });
    MessageBox.Show("Record opened.");
});


Related to Task-based Async Pattern

Sunday, June 27, 2010

Thread-safe dynamic control




In C# 4 (or .NET 4 for that matter) we have dynamic dispatch capability baked in the framework. It not only brings us the dynamic invoking capability, it also allows us to design an object that respond to event.

In the code below, we used DynamicObject to make setting/getting of control's property and calling its method thread-safe. Not only we are able to avoid using extension method(e.g. SetControlPropertyThreadSafe) for accessing control's property and method altogether, we also achieved keeping the original code with minimal modification.

Wednesday, June 23, 2010

First foray to jQuery

<head>
<script src="jquery-1.4.4.js"></script>
 

<script type="text/javascript">    
 $(function() {     
  var toggle = true;

  $("a").click(function() {        
   $("p.neat").showIt(toggle,"fast");    
   toggle = !toggle;
   return false;
  });

  $.fn.showIt = function(b,param) { 
   if (b) 
    $(this).hide(param);
   else     
    $(this).show(param);
  };


 });

 $("p.neat").hide();   
</script>
 
</head>
 
<body>

 <p class="neat" style="width: 200">
 Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
 </p>
 
 <a href="/">Yeah</a> 
</body>

Monday, June 21, 2010

Unboxing nullable value type from object is slow

Contrary to common perception, as is not faster than is-then-cast approach. It's easy to debunk that perception. Just profile


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

class Program
{
    const int Size = 30000000;

    static void Main(string[] args)
    {
        object[] values = new object[Size];
        for (int i = 0; i < Size - 2; i += 3)
        {
            values[i] = null;
            values[i + 1] = "";
            values[i + 2] = 1;
        }

        FindSumWithIsThenCast(values);
            
        FindSumWithAsThenHasThenValue(values);
        FindSumWithAsThenHasThenCast(values);

        FindSumWithManualAs(values);
        FindSumWithAsThenManualHasThenValue(values);

        Console.ReadLine();
    }

    static void FindSumWithIsThenCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            if (o is int)
            {
                int x = (int)o;
                sum += x;
            }
        }
        sw.Stop();
        Console.WriteLine("Is then Cast: {0} : {1}", sum,
                            (long)sw.ElapsedMilliseconds);
    }

    static void FindSumWithAsThenHasThenValue(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            int? x = o as int?;

            if (x.HasValue)
            {
                sum += x.Value;
            }
        }
        sw.Stop();
        Console.WriteLine("As then Has then Value: {0} : {1}", sum,
                            (long)sw.ElapsedMilliseconds);
    }

    static void FindSumWithAsThenHasThenCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            int? x = o as int?;

            if (x.HasValue)
            {
                sum += (int)o;
            }
        }
        sw.Stop();
        Console.WriteLine("As then Has then Cast: {0} : {1}", sum,
                            (long)sw.ElapsedMilliseconds);
    }

    static void FindSumWithManualAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            bool hasValue = o is int;
            int x = hasValue ? (int)o : 0;

            if (hasValue)
            {
                sum += x;
            }
        }
        sw.Stop();
        Console.WriteLine("Manual As: {0} : {1}", sum,
                            (long)sw.ElapsedMilliseconds);
    }

    static void FindSumWithAsThenManualHasThenValue(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            int? x = o as int?;

            if (o is int)
            {
                sum += x.Value;
            }
        }
        sw.Stop();
        Console.WriteLine("As then Manual Has then Value: {0} : {1}", sum,
                            (long)sw.ElapsedMilliseconds);
    }

}
Is then Cast: 10000000 : 303
As then Has then Value: 10000000 : 3524
As then Has then Cast: 10000000 : 3272
Manual As: 10000000 : 395
As then Manual Has then Value: 10000000 : 3282
What can we infer from these figures?
  • First, is-then-cast approach is significantly faster than as approach. 303 vs 3524
  • Second, .Value is marginally slower than casting. 3524 vs 3272
  • Third, .HasValue is marginally slower than using manual has(i.e. using is). 3524 vs 3282
  • Fourth, doing an apple-to-apple comparison(i.e. both assigning of simulated HasValue and converting simulated Value happens together) between simulated as and real as approach, we can see simulated as is still significantly faster than real as. 395 vs 3524
  • Lastly, based on first and fourth conclusion, there's something wrong with as
    implementation ^_^






Tuesday, June 15, 2010

Running total

Query:

with data as
(
select * from 
(values 
  (25),(3),(4),(7),(15),(24),(20),(27), (11)
) as x(y)
)
select y, sum(y) over(order by y) from data

Sample output:
 y  | sum 
----+-----
  3 |   3
  4 |   7
  7 |  14
 11 |  25
 15 |  40
 20 |  60
 24 |  84
 25 | 109
 27 | 136
(9 rows)

Sunday, June 13, 2010

C#'s dynamic leaving Java in the dust

dynamic d = new ExpandoObject();
d.LoremIpsum = Console.ReadLine();
Console.WriteLine("Hello {0}", d.LoremIpsum);
Console.ReadLine();

Wednesday, June 9, 2010

Barebone WCF, the simplest, I believe. Look Ma, No XML!

ServiceStub.cs
using System.ServiceModel;

namespace TestServiceStub
{ 
 [ServiceContract]
 public interface ServiceStub
 {
  [OperationContract] 
  string GetData(string name);
 }
}

Monday, June 7, 2010

Add days to timestamp

Out of the box, this doesn't work:

select CURRENT_TIMESTAMP + 7

Solution:
create function add_days_to_timestamp(t timestamptz, d int) 
returns timestamptz
as
$$
begin
    return t + interval '1' day * d;
end; 
$$ language 'plpgsql';