Welcome to MSDN Blogs Sign in | Join | Help

Asynchronous Programming and Atlas

Few days back, we got into a very interesting performance problem -- To display around 7K data grid entries over a wide spectrum of internet connections. We had to solve the following --

  1. Display of humungous data set in the Grid View in the fastest time possible
  2. To reduce the time it takes a user to review these entries. Thus, we couldn't load the data from the persistent store on every demand.

The conceptual solution that manifested itself was --

  1. To create effective data segmentation and to present the aggregates first;Our aggregates are only two levels deep.
  2. To Pre-fetch and build the server side cache for the detail line items in the aggregates while the user consumes the header level aggregates
  3. Use Atlas to ashynchronously retrieve the data from the server side when the user expands one of the aggregates -- The server side returns the data if it has been cached by the background worker thread. If not, it makes a synchronous call to the persistent storage to retrieve the data, caches the entry and then returns the data back to the client.

Of course, the actual solution will be not to use the background worker threads because they are neither scalable nor robust. But, I just wanted to validate the concept and it works! I will be posting the real production design in the coming days.

Here is the technical breakdown of the concept --

1. Data Segmentation & Atlas Code --

Have a GridView within GridView(the nested GridView is hosted within a table, which sits inside a ItemTemplate). Nesting of child GridView within a table gives it a more cleaner look -- My colleague Sajay came up with this idea as he just couldn't bear the screen design that I initially had :)

Host the parent GridView under an UpdatePanel

<atlas:UpdatePanel runat="server" ID="up_GridView">

<ContentTemplate>

<asp:GridView ID="gridParent" runat="server" AutoGenerateColumns="False" OnRowCommand="GridView1_RowCommand"

OnSelectedIndexChanged="gridParent_SelectedIndexChanged" Width="100%">

<Columns>

<asp:TemplateField ShowHeader="true" HeaderText="Select">

<ItemTemplate >

 <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Select"

Text="+"></asp:LinkButton>

</ItemTemplate>

<ItemStyle VerticalAlign="Top" />

</asp:TemplateField>

<asp:BoundField DataField="Name" HeaderText="Name">

<ItemStyle Width="20%"></ItemStyle>

</asp:BoundField>

<asp:TemplateField ControlStyle-Width="80%">

<ItemTemplate>

<table width="100%">

<tr>

 <td width="100%">

  <asp:GridView ID="gridActivities" runat="server" AutoGenerateColumns="False" Width="100%" CellPadding="3" GridLines="Horizontal">

   <Columns>

  //Child Columns here

   </Columns>

</asp:GridView>

&nbsp;

</td>

</tr>

</table>

</ItemTemplate>

</asp:TemplateField>

</Columns>

 </asp:GridView>

</ContentTemplate>

</atlas:UpdatePanel>

2. Prefetching of data --

/// This class is a singleton

public class TEManager

{

private static TEManager _instance = null;

private static object _lockObject = new Object();

private List<Parent> _parentList = new List<Parent>();

/// <summary>

/// This class provides the only instance of the TEManager to the caller

/// </summary>

/// <returns></returns>

public static TEManager GetInstance()

{

lock (_lockObject )

{

if (_instance == null)

{

_instance = new TEManager();

}

}

return _instance;

}

public List<Parent> GetParentList()

{

//Build the parent list from the persistent storage

//Queue the thread so that we can start building activities for the loaded resources

ThreadPool.QueueUserWorkItem(new WaitCallback(BuildChildCache));

return _parentList;

}

 

protected void BuildChildCache(object state)

{

if ( _parentList != null && _parentList.Count > 0)

{

foreach (Parent parent in _parentList)

{

if ( parent.Children == null )

{

List<Children> children = GetChildrenFromPersistentStorage( parent.ID );

//Lock the parent object so that the synchronous thread can't get to it

lock( parent )

{

parent.Children = children;

}

}

}

}

}

public List<Child> GetChildren(string parentID)

{

List<Child> children = GetChildrenFromCache( parentID );

if (children == null)

{

List<Child> children = GetChildrenFromPersistentStorage( parentID );

Parent parent = GetParentFromCache(parentID);

//lock the parent so that the background thread can't get to it

lock( parent )

{

parent.Children = children;

}

}

return children;

}

private TEManager()

{

}

}

Now, all that needs to be done is to pass the parentID of the selected row on the SelectedIndexChanged event to the TEManager class to retrieve its children. The UpdatePanel takes care of creating a XMLHttpRequest object and loading the children asynchronously.

Happy Programming!

Posted by tarunkohli | 1 Comments
Filed under:

Breaking changes between Vista Beta2 and June CTP

You will find the following document really useful in migrating your WCF code from the February build to the June CTP build --http://wcf.netfx3.com/content/BreakingChangesbetweenVistaBeta2andJuneCTP.aspx
Posted by tarunkohli | 0 Comments
Filed under:

.NET Philosophy

I couldn't help but wonder uncanny similarities between our world and a managed environment, like Microsoft .NET CLR, when I was debugging an object reference issue the other day.


Philosophically speaking, barring few exceptions, we, people from all ethnicities, share a similar pattern or a code to live our lives from birth to demise. We do pretty much the same things at a macro level yet there are idiosyncracies which belong to us and us only. The only constants across this human-function are our birth, human anatomy and our demise from this planet.


So, here goes the parallel analogy in a managed world, An object is instantiated just like we are. It goes through multitude of state changes just like we do, we go through several social and behavioral changes in our lifespan. An object is referenced by other objects just like we associate with people from various ethnical and cultural backgrounds to form a social circle. And, finally, an object is garbage collected when its not needed anymore just like we are when our bodies can't function anymore.


I could go on further explaining the analogy from all the perspectives of object oriented programming in a managed world but I'm sure you get the point.


And, we thought we were not living in a matrix?

 

Posted by tarunkohli | 6 Comments
Filed under:

New Beginnings...

I finally became a blue badge employee few weeks back! I've never seen such a collective enthusiasm to make a difference in ways we deal with our clients and partners. It's truly an exceptional place with immense talent and I'm proud to be part of it.

Posted by tarunkohli | 0 Comments
Filed under:
 
Page view tracker