Welcome to MSDN Blogs Sign in | Join | Help

SYSK 365: How to get your unit tests (test project in Visual Studio 2008, a.k.a. MSTest) run multithreaded

If you want to test code that requires an MTA threading model (e.g. the code being tested uses WaitHandle.WaitAll), you need to change the .testrunconfig file manually and change the threading model from STA to MTA.

 

There are other posts that say for VS 2005, you add the following line to the config file:

<apartmentState type="System.Threading.ApartmentState">

<value__ type="System.Int32">1</value__>

</apartmentState>

 

Unfortunately, same posts say that in VS 2008 you use

<ExecutionThread apartmentState="1" />

 

In my experience, it doesn’t work!  Instead, you should use

          <TestRunConfiguration ...>

            ...

<ExecutionThread apartmentState="MTA" />

</TestRunConfiguration>

 

 

To check the threading model used, add the following line to your test(s):

 

[TestMethod]

public void YourTest()

{

System.Diagnostics.Debug.WriteLine(System.Threading.Thread.CurrentThread.GetApartmentState().ToString());

 

// TODO: Add test logic here

}

 

 

 

 

Posted by irenak | 2 Comments

SYSK 364: AJAX Extensions 1.0 Source Code and Debug Symbols

Did you know that AJAX Extensions source code and debugging symbols are available to everybody at http://www.microsoft.com/downloads/details.aspx?FamilyID=ef2c1acc-051a-4fe6-ad72-f3bed8623b43&DisplayLang=en?

 

 

Posted by irenak | 0 Comments
Filed under: ,

SYSK 363: ‘Software is not made of bricks’ by Ragan Wald

I recently came across this gem http://weblog.raganwald.com/2007/08/bricks.html -- strongly recommended!

 

Here are the section titles to whet your appetite:

 

·         Software is not made of bricks

·         Assumption: it’s all about moving bricks

·         Software is more complicated than bricks

·         Determine the baseline competence required for a project and don’t violate it

·         Software development is difficult to parallelize

·         How to make the team twice as productive without parallelizing everything

·         Software is transfinite

·         How to measure progress on software development projects with estimated work remaining

·         How to measure progress on software development projects with customer satisfaction

·         Building software without treating it like a pile of bricks

I recently came across this gem http://weblog.raganwald.com/2007/08/bricks.html -- strongly recommended!

 

Here are the section titles to whet your appetite:

 

·         Software is not made of bricks

·         Assumption: it’s all about moving bricks

·         Software is more complicated than bricks

·         Determine the baseline competence required for a project and don’t violate it

·         Software development is difficult to parallelize

·         How to make the team twice as productive without parallelizing everything

·         Software is transfinite

·         How to measure progress on software development projects with estimated work remaining

·         How to measure progress on software development projects with customer satisfaction

·         Building software without treating it like a pile of bricks

 

 

Posted by irenak | 2 Comments

SYSK 362: The cost of try/catch

Since I’m still coming across a lot of conflicting recommendations on the “best practices for structure exception handling” (including those coming from different folks from Microsoft), I decided to write a blog post on the topic. 

 

So, what are the benefits and costs with SEH?

 

Let me first address the cost of adding try/catch/finally…

 

John Lee (a peer MCS consultant) did some profiling on his HP Compaq nc8430 Laptop (Dual Core CPU 2.16GHz, 4GB RAM) and, using that hardware, the approximate overhead of adding try/catch per function when exception is not thrown is 0.00001235 ms.  In comparison, getting a connection from a connection pool takes 0.0409662 ms => over 3,000 times slower.  If an exception is thrown from a function nested 10 levels deep with try/catch and rethrow at every level, then the execution time goes up to 0.02010861 ms.

 

Using the numbers above, in my opinion, the cost of try/catch (especially given that, in most cases, the code runs successfully without incurring the cost of throwing an exception) in the context of creating business applications (I’m not talking about critical, real-time or near real time apps which most likely are not written in .NET anyway), is so negligible that the benefits (see next paragraph) far outweigh the cost.

 

As to the benefits…  In my projects, in addition to the standard call stack info, I add the actual data passed to each function in the faulting call stack to the exception message eventually logged to a database.  In most cases, this gives me sufficient data to recreate the problem and do root cause analysis in a fraction of the time it would take without such details. 

 

In summary, if a method can either handle the exception (e.g. correct the problem and/or retry) or has other value-add (e.g. log passed in parameter values in the catch block), then the value of sprinkling the try/catch in every single method (not just at the top-most level) in business level applications is significantly greater, in my opinion, then the cost of the try/catch statements.

 

 

Special thanks to John Lee for doing the profiling!

 

 

Posted by irenak | 4 Comments

Why I have not been writing any new posts...

As much as I love writing the SYSK posts, the reality is that it takes a lot of time...  For the last couple of months, I've been working 14+ hour days consistently...  To make the matters worse, I've learned that this type of activity doesn't even result in a "pat on the back" as, given my role and responsibilities, I'm expected to do this kind of work (and other type of knowledge transfer, mentoring, etc.) internally within Microsoft... 

Bottom line -- the bloging I do here comes out of my personal time, and, with 70+ hour work weeks, there is not much personal time left...

This does not mean that I will not be posting any more...  I just need to get to a more sane work schedule...  So, hang on...  keep checking...  I will be back!

 

Posted by irenak | 8 Comments

SYSK 361: On the importance of signing assemblies from the versioning perspective

There are many reasons for signing your assemblies (security being at the top of my list), but in this post I’d like to address the importance of using a key to sign your assemblies from the versioning point of view.

 

Now, let’s assume for the sake of this discussion, that we’re talking about private assemblies (no GAC).  So, let’s consider a simple factory pattern: client calls a factory class to get an object, the factory uses the context and configuration information to determine the right implementation, creates an instance of that object and returns it to the caller. 

 

For simplicity sake, let’s say you deploy the different implementations of a class in versioned folders, but keep the assembly name, e.g.  

…\bin\Client.exe

…\bin\ClassLibrary\v1.0.0.0\ClassLibrary.dll

…\bin\ClassLibrary\v2.0.0.0\ClassLibrary.dll

 

Once the factory class resolves which class implementation it needs to instantiate, it can use different mechanisms to actually create the object, e.g.:

Assembly asm = Assembly.LoadFrom(@"ClassLibrary\v1.0.0.0\ClassLibrary.dll");

ClassLibraryInterfaces.IClass1 class1 = asm.CreateInstance("ClassLibrary.Class1") as ClassLibraryInterfaces.IClass1;

 

or

 

ClassLibraryInterfaces.IClass1 class1 = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(@"ClassLibrary, Version=1.0.0.0, publicKeyToken=1db56723ca128f1b, culture=neutral", "ClassLibrary.Class1") as ClassLibraryInterfaces.IClass1;

 

or

 

Assembly asm = Assembly.Load(@"ClassLibrary, Version=1.0.0.0, publicKeyToken=1db56723ca128f1b, culture=neutral");

ClassLibraryInterfaces.IClass1 class1 = asm.CreateInstance("ClassLibrary.Class1") as ClassLibraryInterfaces.IClass1;

 

Of course, you would need to give a hint to the runtime about where to find your assembly either via the probing element or codebase:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <runtime>

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

      <probing privatePath="ClassLibrary\v1.0.0.0;ClassLibrary\v2.0.0.0"/>

         </assemblyBinding>

  </runtime>

</configuration>

or

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <runtime>

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

     <dependentAssembly>

        <assemblyIdentity name="ClassLibrary" publicKeyToken="1db56723ca128f1b" culture="neutral" />

        <codeBase version="2.0.0.0" href="ClassLibrary/v2.0.0.0/ClassLibrary.dll" />

        <codeBase version="1.0.0.0" href="ClassLibrary/v1.0.0.0/ClassLibrary.dll" />

      </dependentAssembly>

         </assemblyBinding>

  </runtime>

</configuration>

 

However, if you don’t sign your assembly with a key (i.e. publicKeyToken=”null”), no matter how you implement the class instantiation in the factory class implementation, on the second request, the version portion will be ignored and you’ll get back the instance of the object you created the first time around.  For example, if the first request is for the version 1.0.0.0 and the second is for 2.0.0.0, in both cases, you’ll get back the 1.0.0.0 implementation.

Moreover, if you use probing, you’ll always get the first file name match regardless of the version.

The solution is simple – use a key to sign your assembly.

Also, beware that if you’re using probing you must use Assembly.LoadFrom to avoid type mismatch type of exceptions in cases where the first match is not of the right version.  Or, simply use codebase hints instead (my personal preference).

 

Posted by irenak | 0 Comments

:) When was the color khaki first used for military uniforms?

It was first used by the British in India in 1845, when soldiers turned their highly visible white uniforms khaki by soaking them in mud, coffee, and curry and better blend in with the landscape.

 

Source:  The 365 amazing trivia facts calendar 2007.

Posted by irenak | 5 Comments

SYSK 360: What’s taking up the space in my database? Also, a word about SQL reports…

So, you’ve updated usage stats on your database by running

 

EXEC sp_spaceused @updateusage = N'TRUE'

 

But, you still can’t figure out why it’s reporting much more used space then the data that appears in your tables…

Try running the following query to get number of rows and detailed space usage information for each table and each index.

 

SELECT object_name(object_id) as ObjName,

      index_id as IndexID,

      sum(in_row_data_page_count) as InRowDataPages,

      sum(lob_used_page_count) as LargeObjectPages,

      sum(row_overflow_used_page_count) as RowOverflowPages,

      sum(row_count) as Rows

FROM sys.dm_db_partition_stats

GROUP BY object_id,index_id

GO

Also, there are a number of commonly used reports that are available in SQL Server Management Studio.  Just right-mouse click on the database, and choose Reports -> Standard Reports…

While I am on the SQL reports topic, you can also get a number of useful reports for the entire server,  e.g. All Blocking Transactions, Top Queries by Average CPU time, Top Queries by Average IO, Schema Changes History, Memory Consumption and many more!  Simply, right-mouse click on the server name and choose Reports ->Standard Reports…

Finally, one more query that can come in handy:

SELECT * FROM fn_trace_gettable ('C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\LOG\log.trc', default) GO

 

Special thanks to Curtis Krumel and Saleem Hakani for the queries above!

Posted by irenak | 3 Comments
Filed under:

SYSK 359: How to Purge Workflow Tracking Data Inserted By SqlTrackingService

To my great surprise, after doing a search for a script that would delete the events logged by the almighty SqlTrackingService service, I didn’t find one…  So, I quickly created it (see below), and it seems to do the job just fine given the current table schema implementation used by the service:

IF OBJECT_ID('TrackingPartitionSetName') IS NOT NULL

      DELETE  dbo.TrackingPartitionSetName

GO

 

IF OBJECT_ID('TrackingPartitionInterval') IS NOT NULL

      DELETE dbo.TrackingPartitionInterval

GO

 

IF OBJECT_ID('TrackingProfileInstance') IS NOT NULL

      DELETE dbo.TrackingProfileInstance

GO

 

IF OBJECT_ID('TrackingProfile') IS NOT NULL

      DELETE dbo.TrackingProfile

GO

 

 

IF OBJECT_ID('[dbo].[AddedActivity]') IS NOT NULL

      DELETE [dbo].[AddedActivity]

GO

 

IF OBJECT_ID('[dbo].[RemovedActivity]') IS NOT NULL

      DELETE [dbo].[RemovedActivity]

GO

 

IF OBJECT_ID('TrackingDataItemAnnotation') IS NOT NULL

      DELETE dbo.TrackingDataItemAnnotation

GO

 

IF OBJECT_ID('EventAnnotation') IS NOT NULL

      DELETE dbo.EventAnnotation

GO

 

IF OBJECT_ID('TrackingDataItem') IS NOT NULL

      DELETE dbo.TrackingDataItem

GO

 

IF OBJECT_ID('ActivityExecutionStatusEvent') IS NOT NULL

      DELETE dbo.ActivityExecutionStatusEvent

GO

 

IF OBJECT_ID('UserEvent') IS NOT NULL

      DELETE dbo.UserEvent

GO

 

IF OBJECT_ID('ActivityInstance') IS NOT NULL

      DELETE dbo.ActivityInstance

GO

 

 

IF OBJECT_ID('WorkflowInstanceEvent') IS NOT NULL

      DELETE [dbo].[WorkflowInstanceEvent]

GO

 

IF OBJECT_ID('WorkflowInstance') IS NOT NULL

      DELETE dbo.WorkflowInstance

GO

 

IF OBJECT_ID('[dbo].[Activity]') IS NOT NULL

      DELETE [dbo].[Activity]

GO

 

IF OBJECT_ID('[dbo].[Workflow]') IS NOT NULL

      DELETE [dbo].[Workflow]

GO

 

IF OBJECT_ID('Type') IS NOT NULL

      DELETE dbo.Type

GO

 

 

 

/*  Uncomment the section below if you want to re-set the lookups

 

IF OBJECT_ID('ActivityExecutionStatus') IS NOT NULL

      DELETE dbo.ActivityExecutionStatus

GO

 

-- Reinsert lookups

INSERT dbo.ActivityExecutionStatus VALUES ( 0, N'Initialized' )

INSERT dbo.ActivityExecutionStatus VALUES ( 1, N'Executing' )

INSERT dbo.ActivityExecutionStatus VALUES ( 2, N'Canceling' )

INSERT dbo.ActivityExecutionStatus VALUES ( 3, N'Closed' )

INSERT dbo.ActivityExecutionStatus VALUES ( 4, N'Compensating' )

INSERT dbo.ActivityExecutionStatus VALUES ( 5, N'Faulting' )

GO

 

 

IF OBJECT_ID('TrackingWorkflowEvent') IS NOT NULL

      DELETE [dbo].[TrackingWorkflowEvent]

GO

 

 

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 0, N'Created' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 1, N'Completed' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 2, N'Idle' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 3, N'Suspended' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 4, N'Resumed' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 5, N'Persisted' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 6, N'Unloaded' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 7, N'Loaded' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 8, N'Exception' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 9, N'Terminated' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 10, N'Aborted' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 11, N'Changed' )

INSERT [dbo].[TrackingWorkflowEvent] VALUES ( 12, N'Started' )

       

GO

 

 

IF OBJECT_ID('DefaultTrackingProfile') IS NOT NULL

      DELETE dbo.DefaultTrackingProfile

GO

 

 

INSERT [dbo].[DefaultTrackingProfile] ( [Version], [TrackingProfileXml] )

VALUES (

'1.0.0',

N'<?xml version="1.0" encoding="utf-16" standalone="yes"?>

<TrackingProfile xmlns="http://schemas.microsoft.com/winfx/2006/workflow/trackingprofile" version="1.0.0">

    <TrackPoints>

        <ActivityTrackPoint>

            <MatchingLocations>

                <ActivityTrackingLocation>

                    <Activity>

                        <Type>System.Workflow.ComponentModel.Activity, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Type>

                        <MatchDerivedTypes>true</MatchDerivedTypes>

                    </Activity>

                    <ExecutionStatusEvents>

                        <ExecutionStatus>Initialized</ExecutionStatus>

                        <ExecutionStatus>Executing</ExecutionStatus>

                        <ExecutionStatus>Compensating</ExecutionStatus>

                        <ExecutionStatus>Canceling</ExecutionStatus>

                        <ExecutionStatus>Closed</ExecutionStatus>

                        <ExecutionStatus>Faulting</ExecutionStatus>

                    </ExecutionStatusEvents>

                </ActivityTrackingLocation>

            </MatchingLocations>

        </ActivityTrackPoint>

            <WorkflowTrackPoint>

                  <MatchingLocation>

                        <WorkflowTrackingLocation>

                              <TrackingWorkflowEvents>

                                    <TrackingWorkflowEvent>Created</TrackingWorkflowEvent>                                   

                                    <TrackingWorkflowEvent>Completed</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Idle</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Suspended</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Resumed</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Persisted</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Unloaded</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Loaded</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Exception</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Terminated</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Aborted</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Changed</TrackingWorkflowEvent>

                                    <TrackingWorkflowEvent>Started</TrackingWorkflowEvent>

                              </TrackingWorkflowEvents>

                        </WorkflowTrackingLocation>

                  </MatchingLocation>

            </WorkflowTrackPoint>

        <UserTrackPoint>

            <MatchingLocations>

                <UserTrackingLocation>

                    <Activity>

                        <Type>System.Workflow.ComponentModel.Activity, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Type>

                        <MatchDerivedTypes>true</MatchDerivedTypes>

                    </Activity>

                    <Argument>

                        <Type>System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Type>

                        <MatchDerivedTypes>true</MatchDerivedTypes>

                    </Argument>

                </UserTrackingLocation>

            </MatchingLocations>

        </UserTrackPoint>

    </TrackPoints>

</TrackingProfile>' )

 

GO

 

*/

 

Posted by irenak | 1 Comments

:) What color was named after a bloody 19th-centurey European battle?

Answer:  Magenta. 

 

It was named for the Battle of Magenta, which was fought in 1859 near the town of Magenta in northern Italy during the Franco-Piedmontese war against Austria.  The deep purplish color – on of the first dyes – was discovered soon after the battle and was named to commemorate it.

 

Source:  The 365 amazing trivia facts calendar 2007.

 

Posted by irenak | 2 Comments