C# Threading: COM Apartment Model



Last week I encounterd rather interesting issues regarding threading, .NET and interaction with COM.

Have a look at the following console snippet:
 
class Program
{
    static void Main(string[] args)
    {
        new Test().ShowDialog();
 
        while (Console.ReadKey().Key != ConsoleKey.Enter)
        {
        }
    }
}
 

The Test class is simply a windows form that contains a folder dialog which is obviously used to select folders.

 
public partial class Test : Form
{
    public Test()
    {
        InitializeComponent();
    }
 
    private void btnGo_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog folder = new FolderBrowserDialog();
        if (folder.ShowDialog() == DialogResult.OK)
        {
            txtPath.Text = folder.SelectedPath;
        }
    }
}
 

The preceding snippet will fail as soon as we try to access the folder dialog.



A quick solution would obviously be to simply do what the exception is telling us to do and add the STAThread attribute above the main method. (An assembly that references the System.Windows.Forms namespace's entry point needs to be marked with the STAThread attribute)

But in other cases - when we're working with multiple threads, like in the following snippet, we need to set STA on the actual thread.
 
class Program
{
    static void o()
    {
        new Test().ShowDialog();
    }
 
    static void Main(string[] args)
    {
        Thread t = new Thread(o);
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
 
        while (Console.ReadKey().Key != ConsoleKey.Enter)
        {
        }
    }
}
 

Now you might wonder what this STAThread attribute is all about?

First of all STA (Single Threaded Apartment) relates to a threading model being used in regards to COM objects - the folder dialog in the example makes a call to the Win32 API - which is a COM call.

I am going to attempt to explain this model by using the following crude image:



Looking at the image, notice the two silver rectangles - we call these silver blocks apartments, now an apartment is simply a cozy little place where our com objects live.

You will also notice the abbreviation MTA (Multi Threaded Apartment) - which is the default apartment for com objects in .net (the reason our snippets broke in the first place)

A single threaded apartment (like the name suggests) means that only one thread is allowed to enter our apartment at a time (kinda like a mutex)

The yellow circles represents objects within our apartment, t1 - t4 represents threads trying to access the objects within our apartment (in this case only t4 gains access to the objects, while t1-t3 waits in a queue).

Back in the day before threading, we didn't need our objects to be safe against multiple processes modifying/accessing it at the same time - but as soon as multi threading came into the picture, it became important to isolate our objects.

In addition our application may only contain one MTA (logical), while it may have multiple STA's

Here is some additional reading on the subject:

http://msdn.microsoft.com/en-us/library/ms809971.aspx
http://msdn.microsoft.com/en-us/library/ms693344(VS.85).aspx




Post/View comments
 

New Features - SQL 2008: Filestream



When developing systems, notably ones involving document mis.. uhm management, developers are confronted with the question of where they should store their files.

A simplistic (easy manageable / codeable etc) approach is to simply store/stream the files from a database - unfortunately this approach comes with a performance penalty especially when working with large files.

What is considered large exactly? Well, according to research done by Microsoft - "objects smaller than 256K are best stored in a database while objects larger than 1M are best stored in the filesystem. Between 256K and 1M, the read:write ratio and rate of object overwrite or replacement are important factors" from http://research.microsoft.com/apps/pubs/default.aspx?id=64525

The alternative (like seen in the preceding quote) is to store files on the filesystem, which unfortunately introduces a number of manageability issues like security, integrity etc.

In SQL 2008 however, Microsoft attempts to give us the best of both worlds in the form of the Filestream feature, in which files(blobs) are stored/streamed via the NTFS file system - all managed by SQL.

Lets have a look at how to use/enable this functionality.

By default this feature is disabled, in order to enabled it do the following:

  • Go to Start menu
    • Navigate to All Programs
    • Navigate to Microsoft SQL Server 2008
    • Navigate to Configuration Tools
    • Click on SQL Server Configuration Manager
  • Within SQL Server Configuration Manager
    • Click on SQL Server Services
    • Right click on the SQL Server instance you wish to enable filestreaming
    • Select properties
  • Within Properties
    • Click on the Filestream tab
    • Tick Enable FILESTREAM for Transact-SQL access



      • Enable FILESTREAM for file I/O streaming access tick shares the filestream within Windows
      • Allow remote clients to have streaming access to FILESTREAM data tick allows remote users to access the share
    • Click on Ok

Run the following commands on the master database of the SQL server instance you enabled the filestream feature on (note that its required to restart the instance after running these commands).

 
EXEC sp_configure filestream_access_level, 2
RECONFIGURE
 

For the purpose of this post create a folder named demo, the following query will create a filestream enabled database.

 
CREATE DATABASE FSDemo
ON 
PRIMARY
(
	NAME = FSDemo,
	FILENAME = 'C:\demo\FSDemo.mdf'
),
FILEGROUP FSDemoGroup CONTAINS FILESTREAM
(
	NAME = FSDemoGroup1, 
	FILENAME = 'C:\demo\FSDemo1'
)
LOG ON 
(
	NAME = FSDemoLog, 
	FILENAME = 'C:\demo\FSDemo.ldf'
)
 

A table using the filestream will look something like this:

 
CREATE TABLE [dbo].[documents](
	[documentID] [uniqueidentifier] PRIMARY KEY ROWGUIDCOL NOT NULL DEFAULT NEWID(),
	[name] [varchar](255) NULL,
	[DATA] [varbinary](max) FILESTREAM  NULL
)
 

Thats pretty much the basics around setting up the Filestream feature within SQL 2008.

If you're unsure about how to retrieve/stream/add files to the filestream, click here for some clues.

Additional Reading:
http://research.microsoft.com/apps/pubs/default.aspx?id=64525
http://msdn.microsoft.com/en-us/library/cc949109(SQL.100).aspx




Post/View comments
 
First 16 17 18 19 20 21 22 23 24 25 Last / 62 Pages (124 Entries)

Latest Posts

Be the best stalker you can be


2011-12-13 22:33:54

Syntactic sugar (C#): Enum


2011-08-04 16:50:18

Top 5 posts

Simple WYSIWYG Editor


Creating a WYSIWYG textbox for your website is actually quite simple.
2007-02-01 12:00:00

Moving items between listboxes in ASP.net/PHP example


Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
2008-06-12 17:07:43

Cross Browser Issues: Firefox Word Wrapping


Firefox word wrapping issues
2008-06-09 09:51:21

Populate a TreeView Control C#


Populate a TreeView control in a windows application.
2009-08-27 16:01:03

C# YouTube : Google API


Post on how to integrate with YouTube using the Google Data API
2011-03-12 08:37:51