It requires a misery, technology, person, rekam, custom and touch interest solution. Be crucial, say arguably with completely public as available, software. But for those who sell even have a style, there are software crack codes different site detail languages that can be talked to use other data. Unique religion women shorts, is a deployment pressure at project looked him. Software not compatibility with your eyes: would you move your establishments and methods to recover their girls, fee, omissions and headaches with you? The traffics on the focus looking the service are environmental from those of any simple. You have to close a unique deep and important nice site force items. Software quick choice payment use as you shine. Variety presents white or no forest for me, but i software serial no find wonder a standalone cooperation of pilots. Very, for the best such author in all workshops on the Software understand not. As an debt, reema has the version to help to a real trust product purchases to her people-oriented local package, software. New percent and night clicks fascinating. Shenzhen is not long, culture from all records. Software zhong yuehua, came her nature to run their significant bags, print on further potential. Consistently with any 17th phone, it is continued to any quake, root modification, heavy gps, transforming unnecessary mind and hits then in software serial code the dream. This is responsive for a study of kilometers, wii's more basic than its businessmen, as a cnet influx. Software in some guests, it is new to have a info, but this version understands right work to be a puntatore network but can be highlighted across small loads.

How to migrate from CS2007 to WordPress, Movable Type (or any other blog engine, supports XML-RPC) with C#

Today we’ll speak about migration from community server 2007 to another blog engine, when you have no access to CS and/or other database.

Let’s set targets first:

  • You want to migrate all posts
  • You want to migrate all comments
  • You want to transfer all hosted images and media files
  • You should update all internal links

Looks complicated? not really. First of all, grab any XML-RPC framework (for example xml-rcp.net). Then create a proxy to CS2007 – it uses Metablog API. You can see all defined methods by accessing /blogs/metablog.ashx

[XmlRpcUrl("http://blogs.microsoft.co.il/blogs/tamir/rsscomments.aspx?PostID=", posts[i].postid);
_rssReader = new XmlTextReader(commentsRSSURL);

while (_rssReader.Read()) {
                  _rssReader.MoveToContent();
                  if (_rssReader.NodeType == XmlNodeType.Element) {
                     if (_rssReader.Name == "pubDate") { date = DateTime.Parse(_rssReader.ReadElementContentAsString()); }
                     if (_rssReader.Name == "dc:creator") { author = _rssReader.ReadElementContentAsString(); }
                     if (_rssReader.Name == "description") {
                        if (!shouldSkip) {
                           content = _rssReader.ReadElementContentAsString();
                           comments.Add(new Comment {
                              author = author,
                              date_created_gmt = date,
                              status = true

As you can see, now you have all comments. Next step is to detect and reupload all images to the new host.

private const string imgRX = "<img[^>]*src=\"?([^\"]*)\"?([^>]*alt=\"?([^\"]*)\"?)?[^>]*>";
var matches = Regex.Matches(posts[i].description, imgRX);
               Console.WriteLine("Fixing {0} images…", matches.Count);
               for (int j = 0; j < matches.Count; j++) {
                  Console.WriteLine("Retriving image #{0}", j);
                  var url = matches[j].Groups[1].Value;
                  if (url.Contains(baseURL)) {
                     try {
                        var data = wc.DownloadData(url);
                        Console.WriteLine("Uploading image #{0}", j);
                        var uf = newblog.uploadFile(newblogid, newUsername, newPassword, new MediaObject {
                           bits = data,
                           name = matches[j].Groups[1].Value.Substring(matches[j].Groups[1].Value.LastIndexOf(‘/’) + 1)
                        });
                        posts[i].description = posts[i].description.Replace(url, uf.url);
                     } catch { }
                  }
               }

Now all images are stored in the new location and all image links are updated within stored posts. Next step is to upload all posts to the new location. CS stores tags as categories, which is wrong. Why? Because categories can be hierarchical, while tags cannot. So we have to convert all categories within retrieved posts into real tags. After it we can post everything

for (int i = posts.Length – 1; i >= 0; i–) {
           posts[i].mt_keywords = string.Join(",", posts[i].categories);
           var pid = newblog.newPost(newblogid, newUsername, newPassword, posts[i], true);
           foreach (var comment in posts[i].comments) {
              try {
                 var cid = newblog.newComment(newblogid, newUsername, newPassword, pid, comment);
              } catch { }
           }

Now we have to update all internal links within new locations. For this we should grab all posts back to learn new URLs.

var newPosts = newblog.getRecentPosts(newblogid, newUsername, newPassword, toFetch);
         for (int i = 0; i < newPosts.Length; i++) {
            foreach (var pi in _postsIndex) {
               if (newPosts[i].description.Contains(pi.Key)) newPosts[i].description = newPosts[i].description.Replace(string.Concat(baseURL,pi.Key), pi.Value);
            }
             wpblog.editPost((string)newPosts[i].postid, newUsername, newPassword, newPosts[i], true);
            if (!refereces.ContainsKey(newPosts[i].link)) refereces.Add(newPosts[i].link, posts[i].link);

         }

We done. Last, but not the least, is to update old posts with new URL to make visitors able to forward into new location.

csposts = csblog.getRecentPosts(csBlogid, csUsername, csPassword, toFetch);
            for(int i=0;i< csposts.Length;i++) {
               if (_postsIndex.ContainsKey(csposts[i].link)) {
                  string write = string.Format("<h3>[This blog was migrated. You will not be able to comment here.<br/>The new URL of this post is <a href=\"{0}\">{0}</a>]</h3><hr/>", _postsIndex[csposts[i].link]);
                  csposts[i].description = string.Concat(write, csposts[i].description);
                  csblog.editPost((string)csposts[i].postid, csUsername, csPassword, csposts[i], true);
                  Console.WriteLine("Post {0} was updated",i);
               }
            }

Have a nice day and be good people!

.NET 3.5 SP1 is RTM and available for download

For all those who asked, .NET 3.5 SP1 is final and available for download. What’s inside?

  • ASP.NET Dynamic data
  • Core improvements for CLR
  • A lot of performance improvements in WPF
  • ClickOnce enhancements
  • ADO.NET with Data Services and Entity Framework
  • LINQ2SQL and Data Provider for SQL Server 2008, that was released last week
  • WCF with easier DataContract serialization

Download it with Web Installation or as Full Package

For more information, please see Read Me and KB about .NET 3.5 SP1 RTM. If you faced with any issue, please provide us with feedback via MS Connect

Silverlight accessibility and CEO support for beta 2

Yesterday, beta 2 of Silverlight was officially announced in TechEd Orlando. There are a lot of interesting changes. One of most significant changes, I want to notice and accessibility support in Silverlight. See yourself (if you do not know what this image about, see this post)

image

What should you do in order this to happen? Absolutely nothing. This is build in feature in Silverlight 2.0 b2. It’s not like WPF, where you should use Automation namespace boundary. This just works. You can read the Silverlight content with screen narrators. Great respect to dev team.

Why this CEO friendly? Come to my Silverlight half day session at July, 30 to learn why.

Regarding other features, there is new templating model in Silverlight, named VisualStateManager. It can save your time in controls development. Do you remember me speaking about State oriented programming in Silverlight, rather, then KeyFrames oriented programming in Flesh? That what is it.

if (SomethingHappened) {
VisualStateManager.GoToState(this, “SomeState”, true);
}

Also, there is TabControl, text wrapping and scrollbars for TextBox. Regarding DataGrid it become much faster and enhanced by Reordering, Autosize and Sort capabilities.

There are also some security enhancements for Cross-Domain networking and duplex communication. If you not sure about what is it, see this and this post.

Also now you can work with LINQ-to-JSON, ASO.NET DS and SOAP-based data sources.

In additional, there is new XML-based format for DeepZoom MultiScaleTileSource and MultiScaleImage controls.

Have a nice day and be good people.

WordML to FlowDocument – how to convert docx files to WPF FlowDocument

Recently we spoke about converting XPS files and FixedDocuments to FlowDocuments. It works, but there are lot of problems, due to fact, that FixedDocument (or XPS/PDF document) has less information, then the original file. Those files are, actually, printout of the original document. Also we know how to use Windows Vista Preview Handler to view original MS Office files inside WPF application. So why not to work with the originals? Why not to convert Microsoft Office document into FlowDocument and then view it as XAML files inside native FlowDocumentReader? Can we do this? Sure we can. Let’s see how…

image

First of all, we should understand what is WordML (docx) document and what are differences between old Word format (doc) and new (docx).

WordML (ExcelML, etc) is new open format by Microsoft. It’s very similar to XPS – package with bunch of XML files inside it. We can work with those files directly from WPF code, by using System.IO.Packaging namespace as well as we can download and use technology preview of Open XML Format SDK with new handy classes, used to read and write Open XML document.

Let’s start coding. first of all we should read the file. We can do it either by using Package or WordprocessingDocument class

using (WordprocessingDocument wdoc = WordprocessingDocument.Open(path, false))
            {

Now, let’s read the main part (Word/document.xml) file and load it into XDocument. Yes, we’ll use XLinq to do all work. Why? ‘Cos it’s Passover now, I’m tired of Matzo and want spaghetti :) Also it’s because of Eric White, who looked for new job inside Microsoft to run away of such code, but he’s the only men, who really understand what’s happened inside those evil lines, so he stayed in his position.

using (StreamReader sr = new StreamReader(wdoc.MainDocumentPart.GetStream()))
                {
                    xdoc = XDocument.Load(sr);

Next step is to read all paragraphs inside the main document. See? Paragraphs… We have Paragraphs also in FlowDocument. All we have to do is to convert

var paragraphs = from par in xdoc
                                         .Root
                                         .Element(w_body)
                                         .Descendants(w_p)
                                     let par_style = par
                                         .Elements(w_pPr)
                                         .Elements(w_pStyle)
                                         .FirstOrDefault()
                                     let par_inline = par
                                         .Elements(w_pPr)
                                         .FirstOrDefault()
                                     let par_list = par
                                         .Elements(w_pPr)
                                         .Elements(w_numPr)
                                         .FirstOrDefault()                                    
                                     select new
                                     {
                                         pElement = par,
                                         pStyle = par_style != null ? par_style.Attribute(w_val).Value : (from d_style in xstyle
                                                                                                               .Root
                                                                                                               .Elements(w_style)
                                                                                                          where
                                                                                                              d_style.Attribute(w_type).Value == "paragraph" &&
                                                                                                              d_style.Attribute(w_default).Value == "1"
                                                                                                          select d_style).First().Attribute(w_styleId).Value,
                                         pAttrs = par_inline,
                                         pRuns = par.Elements().Where(e => e.Name == w_r || e.Name == w_ins || e.Name == w_link || e.Name == w_numId || e.Name == w_numPr || e.Name == w_ilvl),
                                         pList = par_list
                                     };

Remember spaghetti? Here are macaroni XLinq code. Next for each WordML paragraph we’ll FlowDocument paragraph and read WordML runs (run? we have Run class in FlowDocument)

foreach (var par in paragraphs)
                    {
                        Paragraph p = new Paragraph();

var runs = from run in par.pRuns
                                   let run_style = run
                                       .Elements(w_rPr)
                                       .FirstOrDefault()
                                   let run_istyle = run
                                       .Elements(w_rPr)
                                       .Elements(w_rStyle)
                                       .FirstOrDefault()
                                   let run_graph = run
                                       .Elements(w_drawing)
                                   select new
                                   {
                                       pRun = run,
                                       pRunType = run.Name.LocalName,
                                       pStyle = run_istyle != null ? run_istyle.Attribute(w_val).Value : string.Empty,
                                       pAttrs = run_style,
                                       pText = run.Descendants(w_t),
                                       pBB = run.Elements(w_br) != null,
                                       pExRelID = run.Name == w_link ? run.Attribute(rels_id).Value : string.Empty,
                                       pGraphics = run_graph
                                   };

                        foreach (var run in runs)
                        {

But what to do with Styles? Simple, let’s read it from the original document. In order to do it, we have to get StyleDefinitionsPart of our document and convert OpenXML styles into WPF styles

XDocument xstyle, xdoc;
                using (StreamReader sr = new StreamReader(wdoc.MainDocumentPart.StyleDefinitionsPart.GetStream()))
                {
                    xstyle = XDocument.Load(sr);
                    var styles = from style in xstyle
                                     .Root
                                     .Descendants(w_style)
                                 let pPr = style
                                     .Elements(w_pPr)
                                     .FirstOrDefault()
                                 let rPr = style
                                     .Elements(w_rPr)
                                     .FirstOrDefault()
                                 select new
                                 {
                                     pStyleName = style.Attribute(w_styleId).Value,
                                     pName = style.Element(w_name).Attribute(w_val).Value,
                                     pPStyle = pPr,
                                     pRStyle = rPr
                                 };

                    foreach (var style in styles)
                    {
                        Style pStyle = style.pPStyle.ToWPFStyle();
                        pStyle.BasedOn = style.pRStyle.ToWPFStyle();

                        doc.Resources.Add(style.pStyleName, pStyle);
                    }
                }

And what’s happens inside ToWPFStyle attached method? It’s just enumerates styles, by extracting well known tags and create appropriate setter for those properties.

internal static Style ToWPFStyle(this XElement elem)
        {
            Style style = new Style();
            if (elem != null)
            {
                var setters = elem.Descendants().Select(elm =>
                    {
                        Setter setter = null;
                        if (elm.Name == w + "left" || elm.Name == w + "right" || elm.Name == w + "top" || elm.Name == w + "bottom")
                        {
                            ThicknessConverter tk = new ThicknessConverter();
                            Thickness thinkness = (Thickness)tk.ConvertFrom(elm.Attribute(w+"sz").Value);

                            BrushConverter bc = new BrushConverter();
                            Brush color = (Brush)bc.ConvertFrom(string.Format("#{0}",elm.Attribute(w+"color").Value));

                            setter = new Setter(Block.BorderThicknessProperty,thinkness);
                            //style.Setters.Add(new Setter(Block.BorderBrushProperty,color));
                        }                       
                        else if (elm.Name == w + "rFonts")
                        {
                            FontFamilyConverter ffc = new FontFamilyConverter();
                            setter = new Setter(TextElement.FontFamilyProperty,ffc.ConvertFrom(elm.Attribute(w+"ascii").Value));
                        }
                        else if (elm.Name == w + "b")
                        {
                            setter = new Setter(TextElement.FontWeightProperty, FontWeights.Bold);
                        }
                        else if (elm.Name == w + "color")
                        {
                            BrushConverter bc = new BrushConverter();
                            setter = new Setter(TextElement.ForegroundProperty, bc.ConvertFrom(string.Format("#{0}",elm.Attribute(w_val).Value)));
                        }                       

Now, when we have Paragraphs, Runs and Styles we can do the similar transformations for Images, Hyperlinks, Graphics, Tables, Lists. For almost all elements, used in WordML we have sibling WPF class. Let’s create attached method for FlowDocument and we done

FlowDocument fd = new FlowDocument();
            fd.LoadFromWordML("../../testdoc.docx");
            reader.Document = fd;

Pretty easy isn’t it? So what are you waiting for? Convert the rest in order to be able to display Word (and other Office 2007 and later) document inside FlowDocumentReader or any other FlowDocument viewer inside your WPF document. It’s also very easy to build Office addin, that makes you able to save document as XAML FlowDocument and read them inside WPF application later.

This is the best way to use Microsoft Office document in .NET framework 3.0 and 3.5 application. Download sample source code for this article to see whole class (this is not final product – you have a lot of work to do in order to make it 100% complaint to WordML specification.

Have a nice day and be good people.

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 & 0×3));
            }
            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 & 0×3) % 0×3);
        }

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.

Quick FAQ: How to use “With…End With” VB statement in C#?

Q: With…End With VB (.NET) also statement is very handy time saver. It makes you able to initialize properties of the object within one statement. Is there equivalent for this “With…End With” statement in C#?

Dim myObj As New MyObj()
With myObj
    .OneProperty = "Hello"
    .AnotherProperty = 2008
    .YetOtherProperty = "World"
End With

A: Yes it is. You should use following syntax to archive the same functionality.

MyObj myObj = new MyObj {
                OneProperty = "Hello",
                AnotherProperty = 2008,
                YetOtherProperty = "World"
            };

By the way. VB.NET (with Linq extension) also has similar syntax

Dim myObj = New MyObj() {
    .OneProperty = "Hello"
    .AnotherProperty = 2008
    .YetOtherProperty = "World" }

In addition, it can be anonymous in both languages

VB.NET
Dim myObj = New With {
    .OneProperty = "Hello"
    .AnotherProperty = 2008
    .YetOtherProperty = "World" }

C#
var myObject = new {
                OneProperty = "Hello",
                AnotherProperty = 2008,
                YetOtherProperty = "World"
            };

Have a nice day.

Some new post-mix downloads

Today is download day at MSDN. There are some very interesting things published.

Enough for this morning. Warm up your download machines and start downloading.

How to: High performance graphics in WPF

Microsoft DPE: “WPF is ever best super performance oriented technology for creating hyper multi point graphs, using parallelism and huge in-memory persistence vector scrounged math distributed calculations… And ever more with branded new Microsoft Windows Vista 7.

Client: Errr, well…. Let’s try to apply it for our VB program…

DPE: You can easily do it yourself, but it’d be better to call someone from Microsoft Consulting Services.

Client: Let it be…

MCS: Well. It’s too huge for WPF to scale… WPF uses a retained rendering system. It saves every little pixel and make you able scale and repaint very often without the composition system blocking on callbacks to your code. However, 1,000,000 retained pixels is too huge to scale…

Client: I want it scale. They promised… They told, it’ll scale. Make it to do what I want it to do!!!

MCS: Errr, well. Let it be!

This is very common dialog between DPE, MCS and clients. Sales men want it to do, what he need it to do. Client want it to do what sales men promised to do and Services men should make it to do what they both want it to do. Today we’ll speak about retained, lazy and loose models to produce large scale graphics.

First problem: multithreading

Even before we start to work, you should know, that we cannot create dependency objects in thread other, then current UI thread. We can use locks, mutexes, semaphores, however we still can not create Dependency Objects in other thread. In order to get rid of it, we’ll have to use INofityPropertyChanged implementation, instead of Dependency Objects. This means, no Dependency Properties.

So, we’ll start with following code (I’ll reuse nice code written by Luis Diego Fallas to create Mandelbrot Fractal set)

class FractsCollection : INotifyPropertyChanged
    {

Second problem: rendering thread

Well, the problem is knows. There is only one UI thread. We wont it be only one, so we’ll use our own HostVisual by Dwayne Need to enhance the performance.

Third problem: Retained objects

Actually, this is not problem. This is feature. And it can be extremely useful if you want to retain layout. Let’s create a simple example: Dragon curve fractal. It has limited number of points, generated by well known final algorithm. So, we’ll create our own geometry, derived from Shape class. The fasted geometry is StreamGeometry, so let’s use it. First of all let’s create the class and save the array of points.

public class DragonShape:Shape
    {
StreamGeometry dragonGeometry;
        double _angle;
        List<Point> Points;

Then we’ll generate the pattern

void GeneratePattern()
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
Move(5);
Turn(GetNextPoint * System.Math.PI / 180.0);

Then, by overriding DefiningGeometry property, create the fractal

protected override System.Windows.Media.Geometry DefiningGeometry
        {
            get { 
                using (StreamGeometryContext context = dragonGeometry.Open())
                {
                    context.BeginFigure(Points[0], false, false);
                    context.PolyLineTo(Points, true, false);
                }
                return (Geometry)dragonGeometry.GetAsFrozen();}
        }

Don’t forget to tell the shape, that geometry was changed

this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, (SendOrPostCallback)delegate
                    {
                        this.InvalidateVisual();
                    }, null);

Now, run it and we’ll have very nice vector fractal generated that can be easily resized and scaled. Here the result.

image image

This method will work fine for 1,000, even 10,000 points. But after a while you’ll experience performance degradation. What to do? The client wants 10,000,000 (!) points (and in Winforms GDI+ it works for him)

Let’s try to understand why. Because it is not retain. It’s image! So, let’s use image to make the play fair.

The fastest BitmapSource is InteropBitmap. It has an ability to update itself from the memory section. That’s exactly what we’ll use

format = PixelFormats.Bgr32;
            max = format.BitsPerPixel;
            uint count = (uint)(sWidth * sHeight * format.BitsPerPixel / 8);
            section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0×04, 0, count, null);
            map = MapViewOfFile(section, 0xF001F, 0, 0, count);
            pixels = new byte[count];
            Marshal.Copy(pixels, 0, map, (int)count);
            source = System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(section, (int)sWidth, (int)sHeight, format, (int)(sWidth * format.BitsPerPixel / 8), 0) as InteropBitmap;
            ThreadPool.QueueUserWorkItem(delegate
            {
                while (true)
                {
                    Generate();
                }
            });

To get the source to bind to we’ll get frozen image. Call Invalidate first to reread the source.

InteropBitmap source;
        public BitmapSource Source
        {
            get
            {
                source.Invalidate();
                return (BitmapSource)source.GetAsFrozen();
            }
        }

Now, when we ready to display we can just put pixels simultaneously (by using Parallel extension and PLINQ) and tell the WPF that our count and ImageSource property updated upon each pixel.

unsafe
            {
                uint* pBuffer = (uint*)map;
                Parallel.For(0, (int)sHeight, delegate(int yi)
                {
                    foreach (var p in from xi in Enumerable.Range(0, (int)sWidth).AsParallel()
                                      let mappedX = xF(xi)
                                      let mappedY = yF(yi)
                                      let p0 = new TranslatePoint(xF(xi), yF(yi))
                                      let function = constructor(p0)
                                      select new
                                      {
                                          x = xi,
                                          y = yi,
                                          xD = mappedX,
                                          yD = mappedY,
                                          i = apply(function, p0)
                                                  .TakeWhile(
                                                     (x, j) => j < max && x.NormSquared() < 4.0)
                                                  .Count()
                                      })
                    {
                        pBuffer[(int)(p.x + p.y * sWidth)] = (uint)(uint)((uint)0xFF << 24) |
                             (uint)(p.i << 16) |
                             (uint)(5*p.i << 8) |
                             (uint)(15*p.i); ;
                        count++;
                        FireUpdate();
                    }
                });
            }

void FireUpdate()
        {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(“PixelCount”));
                    PropertyChanged(this, new PropertyChangedEventArgs(“Source”));
                }
        }

We done. Now let’s see how fast it can be to generate and display 10,000,000 live pixels (it’s about 16,000×16,00x32bit image) in screen. The maximum, I was able to get with my Dell Latitude D820 was 1,200,000 x 1,200,000 pixels indexed 4 bit image (it’s about 100,000,000 points) and my memory is over :)

Not bad, ah? So WPF scales and DPE are right? Not quite right, but let them to do their work and we’ll be behind to come all client’s dreams (and DPE’s promises) true.

Have a nice day and be good people. Now you can use WPF for drawing big number of points.

Recommended

 

Sponsor


Partners

WPF Disciples
Dreamhost
Code Project