Saturday, February 19, 2011

To Box or not to box?

 

So recently I started refreshing my knowledge in .net basics since I'm starting to seek for a new job, and I ran into a subject that Shani Raba once told  me about.

I am talking about boxing and unboxing of value types.

let's starts from the really basics.. I'm sure most of you know that in .net Framework we have two types, value types and reference types. value types are the type we mostly use, these are the common types like int32, bool, decimal and so on, these types are located in the thread stack(in the process we use) and we don't need to initialize them(with the new keyword). on the other hand we have the reference types, these types are located on the managed heap, they are heavier since they have a overhead of additional members and they are garbage collected.

I must also point that value types derive from System.ValueType which derives from System.Object.

watch this code sample:

array

So what actually happens here? The ArrayList.Add method takes and Object as a parameter, so for each integer we want to insert to the list it has to cast to Object. however the integer is stored on the stack and the list expects a Object from the managed heap. In that case the CLR is using a mechanism called Boxing.

what is Boxing:

1) Memory is allocated on the managed heap, according to the size of the value type pluse some extra overhead.

2) fields from the value types are copied to the new object on the managed heap.

3) the CLR returns the address of the value which is now it's reference.

So in our example we actually created 20 new objects on the managed heap, and as we stated in the begining of the post it's a big overhead. Now what will happen if we will write the following code?

unb

Now we try to convert the Object to int. That action is called UnBoxing, and that's what actually happens is that the CLR generates a pointer to the data in the Object, the one on the heap. As you can understand the UnBox action is much more "cheap" than the box action.

So what can we do to avoid this overhead:

1) use proper methods and overloads, for example the Console.WriteLine method has about 12 overloads, so if you have an integer you can send it as a parameter to the writeline method (by that using the overload which takes int as a parameter), and you should not use the ToString method for this.

2) Box your value type in a single place, and use that boxed type for all the places you need.

3) use Generics and Interfaces when possible.

 

BRIUT

Saturday, February 5, 2011

Working with threads in silverlight

Lets say that we have a silverlight application that gets updates from an outer service every X seconds. the application calls the service every X seconds and waits for the answer(async-way of course).

The most trivial way is to use a timer that every X seconds the Tick event will raise and call our service.

In order to do so we have got the System.Threading.Timer to use. the code will look like that:

       public MainPage()
       {
           InitializeComponent();

           var timer = new Timer(TimerTick, null, new TimeSpan(0, 0, 0, 1), new TimeSpan(0, 0, 0, 5));
       }

       private void TimerTick(object state)
       {
           var client = GetClient();
           client.GetUpdatesComplete += GetUpdate_OnComplete;

           client.GetUpdates();
       }

       private void GetUpdate_OnComplete(object sender, GetUpdatesCompleteEventArgs e)
       {
           if (e.Error == null)
           {
               MyTextBox.Text = "Hello world! the time is " + DateTime.Now;
           }
           else
           {
               MyTextBox.Text = "Error!";
           }

       }

But when we will run the code we will get an error:

"Cross-thread operation not valid: Control 'MyTextBox' accessed from a thread other than the thread it was created on."

The meaning of this error is that we are trying the access the UI from other thread rather than the UI thread. and in silverlight, this is not possible.

So what we do?? we use the method Dispatcher.BeginInvoke() that will change the property via the UI thread. the code will look like this:

        private void GetUpdate_OnComplete(object sender, GetUpdatesCompleteEventArgs e)
        {
            if (e.Error == null)
            {
                Dispatcher.BeginInvoke(() => MyTextBox.Text = "Hello world! the time is " + DateTime.Now);
            }
            else
            {
                ispatcher.BeginInvoke(() => MyTextBox.Text = "Error!");
            }

        }

This is all nice and pretty but there might be a problem. this thread will run no matter what is the state of the UI. even if the UI is stuck, because it runs from another thread….

If we want to use timer that will run on the UI thread we can use DispatcherTimer , and we won't have to call the Dispatcher.BeginInvoke().

Did you got confused?? lets summarize:

1) If you need to use threads that should run each X seconds, no matter what the UI state is, and don't want it to effect the UI – use Timer and Dispatcher.BeginInvoke().

2) If you want that your timer will not run while the UI is stuck or have al long processing to do – use DispatcherTimer.

WCF service with multiple http-hosts

Introduction:

In the IIS configurations there is a section to configure which address are allowed to access the web-site in term of host-names.

For example, we can access our application in several ways:

http://IP/MyApp/My.aspx

http://server-name/MyApp/My.aspx

http://MyLoadBalancerName/MyApp/My.aspx

We can configure this in the IIS for our web-site:

On IIS 6:

right click on the web-site->properties-> web-site tab –> advanced

On IIS 7 and up:

right click on the web-site –> Edit bindings

image

*on IIS 7 on windows 7, as you can see the configuration is for all kinds of bindings, not just http.

The default is an empty host name => you can access any way you want. but you can set all kinds of host-names for all kind of ports. this way you are limiting the access to your site, and of course this is the best-practice for securing your site. usually we will configure our server-name and our load balancer server if we have one.

So what does WCF has to do with all of that??

Well, when you configure more that one host-name to a specific binding(let's say http) on your IIS and try to access a service on the site via that binding you'll get not-so-nice error that says that you have too many http-address but you only allowed to have one:

"This collection already contains an address with scheme http. There can be at most one address per scheme in this collection."

The solution is quiet simple – you can set an address filter in the server config that tells him to access the server with a specific address only. you can do this with baseAddressPrefixFilter:

<system.serviceModel>   
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="http://MyHostName"/>
<add prefix="net.tcp://MyHostName"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
........
</system.serviceModel>
In this case the wcf will try to access the specific address for the binding and will ignore all the other headers.
Some notes:
*If you want, there are other solutions that includes creating a serviceFactory to solve the problem.
*This is relevant for .net 3/3.5. in .net 4 there is a property called MultipleSiteBindingsEnabled that handles this issue, and by setting it to true you can freely use wcf with several http-hosts.

Saturday, January 29, 2011

"Access denied" in accessing arcgis server from remote

A couple of weeks ago we upgraded our gis server(esri) from 9.3 to 9.3.1. nothing too much exciting about that except for the following problem:

After we uninstall the ags 9.3 from the server we restart it. than, we installed 9.3.1 and all good(allegedly). than we wanted to manage the gis server from another server. when doing the configuration we got:

"Access Denied: Either the SOM service on machine is not started or the user attempting this connection is not a member of the agsuser or agsadmin group and cannot be granted access to the SOM."

Of course everything was started and we could manage the gis server from local ArcCatalog.

After hours of searching and google-ing we found that our Dcom was disabled(remember the restart? that's what probably cause the Dcom settings to change).

The fix:

On the server, go to Start > Run and type dcomcnfg
Component Services > Computers and right click on My Computer-> Choose Properties.
In the Default Properties tab => ensure that "Enable Distributed COM on the computer" is checked.

That what solved our problem, but here's a link to 1000 solutions for this same problem:

http://forums.esri.com/thread.asp?c=158&f=1702&t=220661&mc=21#668317

Good luck.

Friday, January 21, 2011

Silverlight control template–Part II

As I promised in my last post I will show you how to change the visual appearance of controls that are not content control.

For this explanation I will create round text box.

I will start from the end and show you the complete result:

image

And the style code:

<Style x:Key="TextBoxStyle" TargetType="TextBox">
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="TextBox">
                      <Grid x:Name="RootElement">
                          <Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" 
                                  CornerRadius="15" BorderBrush="Black" >
                              <ScrollViewer Height="Auto" 
                                                    x:Name="ContentElement" Width="100"
                                                    BorderThickness="0" 
                                                    IsTabStop="False" 
                                                    Padding="{TemplateBinding Padding}" 
                                                    Margin="5"/>
                          </Border>
                      </Grid>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
</Style>

At first, it's look exactly the same as the example of the round button. but the big difference is in the bolded text. because text box does not have a content we cannot use content presenter to holds it's content. but every textbox has the place where you can write things, and you need some way to present it in your template!

In my case, The ScrollViewer comes to help. and why? because in the textbox defenition it defines "place holder" for the text area, in order for us to be able replace it with another control. so I defined a ScrollViewer and gave it the name of the part "ContentElement".

What? Where? How?

From msdn:

[TemplatePartAttribute(Name = "ContentElement", Type = typeof(FrameworkElement))]
[TemplateVisualStateAttribute(Name = "InvalidUnfocused", GroupName = "ValidationStates")]
[TemplateVisualStateAttribute(Name = "InvalidFocused", GroupName = "ValidationStates")]
[TemplateVisualStateAttribute(Name = "ReadOnly", GroupName = "CommonStates")]
[TemplateVisualStateAttribute(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualStateAttribute(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualStateAttribute(Name = "Unfocused", GroupName = "FocusStates")]
[TemplateVisualStateAttribute(Name = "Valid", GroupName = "ValidationStates")]
[TemplateVisualStateAttribute(Name = "MouseOver", GroupName = "CommonStates")]
[TemplateVisualStateAttribute(Name = "Focused", GroupName = "FocusStates")]
public class TextBox : Control

The control defines TemplatePart that can be any FrameworkElement and by defining this part it will behave as text holder for the text box. (p.s the state the you see are the visual state that you can define to the control)

Here is the same code with button as ContentElement part of the textbox:

(The text is not the content of the button! you can write whatever you like in runtime)

image

All silverlight controls defines parts that helps you change the control's appearance without loosing it's behivor! all you need to do is go to the control definition is msdn – and start desigining your controls!

Silverlight rocks!!