Monday, April 14, 2008

My TechEd ‘08 presentation slides download

I do not know why, but for some reason in development section of TechEd website there are only two recording and no presentations. I do not want to wait for them to upload (we sent all presentations a while ago), so here it comes. My TechEd presentation DEV335 - Game Development Using Microsoft’s Latest Technologies. I have no recordings by now (so pity), so you’ll have to wait for Microsoft to encode and upload it. Upon it will be done, I’ll publish it here.
There is no real reason to upload samples – they will not work without all environment we had there.

Download full slides from my TechEd presentation (PPT 7,165 KB) >>

If you have any questions, feel free to contact me by using contact form or LinkedIn profile. You also can send me a message by twitter

te08

Parallel programming? Well, it’s all about CPU affinity or how to set processor affinity in WPF

Parallel computing is very cool technology, that makes you able to leverage tasks between processors in your system. Today it’s already impossible to buy single processor computer – when you’ll buy new PC, you’ll probably get dual core CPU at least. Today we’ll speak about how to manage affinities of tasks between CPUs in your system. For this purpose we’ll create a small game, named CoreWars. So, let’s the show begin.

image

What we want to do? Simple game, that includes some complicated math, executed large number of times. Here the code of one Dice roll

void SetDice()
        {
            List<Dice> dices = new List<Dice>();
            for (int i = 0; i < MaxTries; i++)
            {
                double x = rnd.NextDouble();
                double y = rnd.NextDouble();
                double g = (Math.Pow(x, 2) + Math.Pow(y, 2) - rnd.Next()) / (Math.Sqrt(2) * y + Math.Sqrt(2) * ((x - Math.Sqrt(2)) - 1));
                dices.Add((Dice)((int)g & 0x3));
            }
            int mP = dices.Count(dice => dice == Dice.Paper);
            int mR = dices.Count(dice => dice == Dice.Rock);
            int mS = dices.Count(dice => dice == Dice.Scissors);

            int m = (mP > mR) ? mP : mR;
            m = (m > mS) ? m : mS;

            CurrentDice = (Dice)((m & 0x3) % 0x3);
        }

Don’t even try to understand what’s going on here. The result is one dice state Paper, Rock or Scissors (the old kinds game). Now we want to run this number of times and affine each thread to one of our system’s core. How to do it?

Simple way – ask what thread are you running, then use ProcessorAffinity property of the ProcessThread to your CPU id.

ProcessThread t = Process.GetCurrentProcess().Threads.OfType<ProcessThread>().Single(pt => pt.Id == AppDomain.GetCurrentThreadId());
t.ProcessorAffinity = (IntPtr)(int)cpuID;

Very good, but what’s this warning about “System.AppDomain.GetCurrentThreadId()' is obsolete: 'AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread.  http://go.microsoft.com/fwlink/?linkid=14202 ” ? Why this happens to me? The simple answer is Thread Processor Affinity never was most reliable thing in Windows (as well as ThreadID). But we still want to make it. What to do?

Let’s go a bit unmanaged. We’ll use SetThreadAffinityMask and GetCurrentThread WinAPI methods to achieve what we want to.

[DllImport("kernel32.dll")]
        static extern IntPtr GetCurrentThread();
[DllImport("kernel32.dll")]
        static extern IntPtr SetThreadAffinityMask(IntPtr hThread, IntPtr dwThreadAffinityMask);

SetThreadAffinityMask(GetCurrentThread(), new IntPtr(1 << (int)cpuID));

SetThreadAffinityMask(GetCurrentThread(), new IntPtr(0));

So far, so good. Now threads. This step is very trivial

ParameterizedThreadStart pts = new ParameterizedThreadStart(dr.ThrowDices);
Thread t = new Thread(pts);
t.SetApartmentState(ApartmentState.MTA);
t.IsBackground = true;
t.Start(i);

We need also context switch (you remember, WPF)

ThreadPool.QueueUserWorkItem(delegate
            {
                int w = WaitHandle.WaitAny(wcs);
                Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate(object o)
                {                   
                    tb.Text = string.Format("The winner is CPU #{0}", o);
                }, w);
            });


Now, what to do with binding? To Bind or not to Bind – that is the question! My answer is to bind! Remember, you need also a small piece of CPU time to process UI events and push frames in renderring thread. Let’s roll dices.

SetThreadAffinityMask(GetCurrentThread(), new IntPtr(1 << (int)cpuID));

            App.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
            {
                base.Clear();

                if (CollectionChanged != null)
                    CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset, null));
            }, null);

            for (int i = 0; i < MaxIteractions; i++)
            {
                DiceRoller dr = new DiceRoller();
                App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
                   {
                       base.Add(dr);

                       if (CollectionChanged != null)
                           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, dr));
                   }, null);
            }
            SetThreadAffinityMask(GetCurrentThread(), new IntPtr(0));
            ResetEvent.Set();

Also do not forget to implement INotifyCollectionChanged on result collection and INotifyPropertyChanged on dice object.

After all preparations done, we can start to build basic user interface for the presentation layer. Main window

<StackPanel Name="Root">
        <StackPanel Name="LayoutRoot" Orientation="Horizontal"/>
        <Button Content="Start battle" Click="Button_Click"/>
        <TextBlock Name="tb" TextAlignment="Center" FontSize="15" Visibility="Collapsed"/>
    </StackPanel>

Templates

<DataTemplate DataType="{x:Type l:DiceRoller}" x:Key="drt">
            <Rectangle Width="5" Height="5">
                <Rectangle.Style>
                    <Style>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=CurrentDice}" Value="Paper">
                                <Setter Property="Rectangle.Fill" Value="Red"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=CurrentDice}" Value="Rock">
                                <Setter Property="Rectangle.Fill" Value="Black"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=CurrentDice}" Value="Scissors">
                                <Setter Property="Rectangle.Fill" Value="Blue"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Rectangle.Style>
            </Rectangle>           
        </DataTemplate>
        <ItemsPanelTemplate x:Key="wpt">
            <WrapPanel/>
        </ItemsPanelTemplate>

We done. the only task to perform is to detect the number of CPUs in the system and put appropriate number of content controls to show the race result. Do not forget binding too.

pc = Environment.ProcessorCount;

            for (int i = 0; i < pc; i++)
            {
                HeaderedContentControl hcc = new HeaderedContentControl();
                hcc.Width = this.Width / pc;
                hcc.HorizontalAlignment = HorizontalAlignment.Stretch;
                hcc.Header = string.Format("CPU {0}",i);

                ItemsControl ic = new ItemsControl();
                ic.ItemsPanel = Resources["wpt"] as ItemsPanelTemplate;
                ic.ItemTemplate = Resources["drt"] as DataTemplate;
                hcc.Content = ic;
                LayoutRoot.Children.Add(hcc);

                DiceRollers dr = new DiceRollers();
                this.Resources.Add(string.Format("roller{0}", i),dr);              

                Binding b = new Binding();
                b.Source = dr;
                b.IsAsync = true;
                b.BindsDirectlyToSource = true;
                b.Mode = BindingMode.OneTime;
                ic.SetBinding(ItemsControl.ItemsSourceProperty, b);
            }

That’s all. Now we can race our dices and see what CPU works better. For real life scenario, this sample looks absolutely stupid, but just thing about processor affinity in Parallel Extension CTP – why not to make us able to use it? The answer is – K.I.S.S (keep it simple, stupid). And as for me, I do not like to be stupid and I want to manage affinities! I need high performance for my applications and only me can decide to which processor dispatch which task and how.

Have a nice day and be good people.

Source code for this article.

Sunday, April 13, 2008

Quick WPF Tip: Change as you type in WPF when binded to the same DependencyProperty

Let’s write this simple code:

<TextBox Name="source"/>
<TextBlock Text="{Binding ElementName=source, Path=Text}"/>

Now, the value of TextBlock will be changed during typing in TextBlock. However, let bind both to some DependencyProperty

<TextBox Text="{Binding Path=SomeProp}"/>
<TextBlock Text="{Binding Path=SomeProp}"/>

Now, TextBlock will be updated only when you leave TextBox. Why this happens? It’s because by default UpdateSourceTrigger  property of Binding set to LostFocus, when binded to DepndencyObject.

So, how to fix it? Simple set UpdateSourceTrigger explicitly.

<TextBox Text="{Binding Path=SomeProp, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Path=SomeProp, UpdateSourceTrigger=PropertyChanged}"/>

Hurah, the value of the TextBlock (as well as the value of underlying dependency property) changing while typing into TextBox.

Have a nice day.

To OLE / From OLE color translator in WPF

In GDI+ (Winforms) world, there was very handy class inside System.Drawing. It named ColorTranslator and it used to translate from OLE integer color value into GDI+ Color and vice verse. In WPF there is no such class, so if you’re working with old COM/COM+ application you have either reference System.Drawing.dll or write those two methods yourself. I prefer to write it :)

public static class ColorTranslator
    {
        const int RedShift = 0;
        const int GreenShift = 8;
        const int BlueShift = 16;
        /// <summary>
        /// Translates an Ole color value to a System.Media.Color for WPF usage
        /// </summary>
        /// <param name="oleColor">Ole int32 color value</param>
        /// <returns>System.Media.Color color value</returns>
        public static Color FromOle(this int oleColor)
        {
            return Color.FromRgb(
                (byte)((oleColor >> RedShift) & 0xFF),
                (byte)((oleColor >> GreenShift) & 0xFF),
                (byte)((oleColor >> BlueShift) & 0xFF)
                );
        }

        /// <summary>
        /// Translates the specified System.Media.Color to an Ole color.
        /// </summary>
        /// <param name="wpfColor">System.Media.Color source value</param>
        /// <returns>Ole int32 color value</returns>
        public static int ToOle(Color wpfColor)
        {
            return wpfColor.R << RedShift | wpfColor.G << GreenShift | wpfColor.B << BlueShift;
        }
    }

Have a nice day and be good people.

Two quick WPF tricks: Show tooltip on disabled control and accessibility for WPF button

Question: When my control is disabled, it does not show any toolip, in spite of the fact, that it has one. What to do?

Answer: Use ToolTipService.ShowOnDisabled="True" attached property

 

Question: You wrote grate article about accessibility of WPF. How to use it with QTP/WinRunner (or any other visual test programs). However it works on lists and other items controls, but not on content controls. What to do?

Answer: It works as well. More, then this. It works also without “style" hack” in .NET 3.5. See yourself

image

Here the source code

<StackPanel Orientation="Vertical" DataContext="{StaticResource datas}">       
        <ListBox ItemsSource="{Binding}" ItemTemplate="{StaticResource t1}" ItemContainerStyle="{StaticResource stl}" IsSynchronizedWithCurrentItem="True"/>
        <Button Content="{Binding Path=Prop2}" ToolTip="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Content}"/>
        <Button Content="{Binding Path=Prop2}" ToolTipService.ShowOnDisabled="True" IsEnabled="False" ToolTip="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Content}"/>
    </StackPanel>

It works. If you’re using 3.0 just set AutomationProperties.Name property by using setters in style as described in the article and this will work for you.

<Style x:Key="stl">
            <Setter Property="AutomationProperties.Name" Value="{Binding Prop2}"/>
        </Style>

Have a nice day

How to have more, then one forms in page and be able to submit it to server without page refresh using ASP.NET AJAX

Someone asked me in Meet an Expert lunch in TechEd about having more, then one server forms in one page, using ASP.NET AJAX. The answer was simple – make only one visible at one time. Other words, hide all and show only one relevant

<script runat=server language="C#">
private void Page_Load(object sender, System.EventArgs e)
{
Form1.Visible = !Form1.Visible;
Form2.Visible = !Form2.Visible;
}

<form id="Form1" runat="server" >…
<form id="Form2" runat="server" visible="false">…



That’s all. However, what to do if you need to show them all? Let’s try to understand. First of all, let’s make them client based




<form id="form1" >…

<form id="form2" >…




Then we should handle onsubmit method and neutralize it, before the page will be reloaded (we do not want reloads – AJAX rulez!)




<form id="form1" onsubmit="onSubmit(this); return false;">…

<form id="form1" onsubmit="onSubmit(this); return false;">…




So, the final code will looks as following (there are some of such forms):




<form id="form1" onsubmit="onSubmit(this); return false;">

    <div>


    <h2>Client Form 1</h2>


    <input type="text" id="val" />


    <input type="submit" value="Submit 1" />


    </div>


    </form>




Then, let’s have one server side form, that will handle our requests




<form runat="server">

<asp:Label ID="Result" runat="server"/>




And now, let’s submit our results there. Yes, we can access server side controls from client side JavaScript




<script type="text/javascript">

       function onSubmit(sender)


       {


            var what = sender["val"].value;


            if(what == "")


                what = "nothing";


            $get("Result").innerHTML=sender.id+" tells you "+what;



       }




Well, but as you, probably understand, there is no real submit was performed. We need client-server-client roundtrip in order to do it. What to do? The answer is PageMethods.



Let’s add simple page method, that formats the string and added time tag




<script runat="server">

            [System.Web.Services.WebMethod]


            public static string UpdatePanel(string senderID, string what)


            {


                return string.Format("{0} tells you {1} at {2} with server roundtrip", senderID, what, DateTime.Now);


            }


       </script>




One we have such. All we have to do is to enable page methods by using ScriptManager




<form runat="server">

    <h2>Result</h2>


        <asp:ScriptManager runat="server" EnablePageMethods="true" />


        <asp:Label ID="Result" runat="server"/>


    </form>




And then, call it from javascript




function onServerSubmit(sender)

       {


            var what = sender["val"].value;


            if(what == "")


                what = "nothing";


            PageMethods.UpdatePanel(sender.id,what,onServerSubmitCompleted);



       }

function onServerSubmitCompleted(value)


       {


         $get("Result").innerHTML=value;


       }




We done. BTW, if we’ll try to pass HTML object into server, we’ll get "Cannot serialize object with cyclic reference within child properties" exception – this is not bug, this is warlock for bad HTML programmers. If you want to be able to pass whole form (HTML object) into server you’ll probably have to either use LosFormatter, or any other custom HTML serializer to do it.  Want to know more about it? Maybe another time.



Have a nice week and be good people.



Source code for this article

Friday, April 04, 2008

TechEd in over the corner and we are ready! What about you?

After a lot of work I’m ready for TechEd. It worth me a lot of blood, sweat and tears until it started to work as I expected. What our session about? In one sentence – Game Development. In number of sentences – we’ll build online car racing multiplayer game, that will run on XBOX, Windows, Linux, Mac and mobile phone. All this will be tied up with Windows Live services. During the session, XBOX will play with WPF and Novel Suse Linux will run ASP.NET and play with IIS7. Don’t believe me? Come and see. Here small video, that demonstrates some of this session results. There are much more to see…

See you there 8th of april, 10:45 in Knaan hall of Hilton hotel in Eilat.