All notes
LibraryReferenc

System

Datetime

DATETIME supports 1753/1/1 to "eternity" (9999/12/31), while DATETIME2 supports 0001/1/1 through eternity. Thus conversion of a datetime2 data type to a datetime data type may result in out-of-range value. See this SO.


DateTime date1 = new DateTime(2008, 5, 1, 8, 30, 52);
DateTime date1 = DateTime.Now;
DateTime date2 = DateTime.UtcNow;
DateTime date3 = DateTime.Today;

string dateString = "5/1/2008 8:30:52 AM";
DateTime date1 = DateTime.Parse(dateString, 
                   System.Globalization.CultureInfo.InvariantCulture);

Interfaces

IDisposable

The use of this interface is to release unmanaged resources such as window handles, or open files and streams, as well as manage resources such as System.Drawing.Bitmap and DbConnection.

Proper use of the IDisposable

SO: proper use of the IDisposable.

Because the IDisposable.Dispose() implementation is called by the consumer of a type when the resources owned by an instance are no longer needed, you should either wrap the managed object in a SafeHandle (the recommended alternative), or you should override Object.Finalize() to free unmanaged resources in the event that the consumer forgets to call Dispose.

When using Finalize() to call Dispose(), you need a way for Finalize() to tell Dispose() that it should not touch any managed resources (because they might be freed by GC and not be there anymore), while still freeing unmanaged resources. The standard pattern to do this is to have Finalize() and Dispose() both call a third(!) method; where you pass a Boolean saying if you're calling it from Dispose() (as opposed to Finalize()), meaning it's safe to free managed resources.

If the user calls Dispose() on your object, then everything has been cleaned up. Later on, when the garbage collector comes along and calls Finalize, it will then call Dispose again -- which is redundant. You can improve this by calling GC.SuppressFinalize() in the Dispose() method.

The SuppressFinalize optimization is not trivial, as your objects can live a long time waiting on the finalizer queue.

Which one is the place for me to cleanup unmanaged resources? The answer is: It's your choice! But choose Dispose.

The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a IDisposable.Dispose implementation.

How to call

You can call the object's IDisposable.Dispose implementation in one of two ways:

The using statement is actually a syntactic convenience. At compile time, the language compiler implements the intermediate language (IL) for a try/catch block.


// Implicitly.
using (StreamReader sr = new StreamReader(filename)) {
    txt = sr.ReadToEnd();
}

// Explicitly
StreamReader sr = null;
try {
   sr = new StreamReader(filename);
   txt = sr.ReadToEnd();
}
finally {
   if (sr != null) sr.Dispose();     
}

Implementation in Heritance

If you are defining a base class that uses unmanaged resources and that either has, or is likely to have, subclasses that should be disposed, you should implement the IDisposable.Dispose method and provide a second overload of Dispose.

For base class:

Subclasses should implement the disposable pattern as follows:

Base:


using System;

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;

   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
        // This object will be cleaned up by the Dispose method.
        // Therefore, you should call GC.SupressFinalize to
        // take this object off the finalization queue 
        // and prevent finalization code for this object
        // from executing a second time.
      GC.SuppressFinalize(this);
   }

   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         // Free any other managed objects here.
         //
      }

      // Free any unmanaged objects here.
      //
      disposed = true;
   }

    // In C#, you override Object.Finalize by defining a destructor.
   ~BaseClass()
   {
      Dispose(false);
   }
}

Derived:


using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class DerivedClass : BaseClass
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   // Instantiate a SafeHandle instance.
   SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);

   // Protected implementation of Dispose pattern.
   protected override void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.
      }

      // Free any unmanaged objects here.

      disposed = true;
      // Call base class implementation.
      base.Dispose(disposing);
   }
}

Configuration

By adding an application configuration file (app.config file) to a C# project, you can customize how the common language runtime locates and loads assembly files.

When you build your project, the development environment automatically copies your app.config file, changes the file name of the copy to match your executable, and then moves the copy to the bin directory.

An administrator can control which protected resources an application can access, which versions of assemblies an application will use, and where remote applications and objects are located. Developers can put settings in configuration files, eliminating the need to recompile an application every time a setting changes.

Managed code can use the classes in the System.Configuration namespace to read settings from the configuration files, but not to write settings to those files.

SO: Reading settings from app config.

For Sample App.config like below:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="countoffiles" value="7" />
    <add key="logfilelocation" value="abc.txt" />
  </appSettings>
</configuration>

You read the above app settings using code shown below:


using System.Configuration;

string configvalue1 = ConfigurationManager.AppSettings["countoffiles"];
string configvalue2 = ConfigurationManager.AppSettings["logfilelocation"];

Three types of configuration files: machine, application, and security.

Machine.config, contains settings that apply to an entire computer. This file is located in the "%runtime install path%\Config directory".

Diagnositics

MSDN. The System.Diagnostics namespace provides classes that allow you to interact with system processes, event logs, and performance counters.

Stopwatch

SO: measure elapsed time during execution.


using System.Diagnostics;

var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < N_ITER; i++) {
    // cpu intensive sequence
}
stopwatch.Stop();
elapsed_time = stopwatch.ElapsedMilliseconds;

Process, ProcessStartInfo

Namespace: "System.Diagnostics".

ProcessStartInfo.UseShellExecute

True if the shell should be used when starting the process; false if the process should be created directly from the executable file. The default is true. Setting this property to false enables you to redirect input, output, and error streams.

Process.WaitForExit

MSDN: waitforexit.

Sets the period of time to wait for the associated process to exit, and blocks the current thread of execution until the time has elapsed or the process has exited. To avoid blocking the current thread, use the Exited event.

Process.StandardOutput

MSDN: StandardOutput.

When a Process writes text to its standard stream, that text is normally displayed on the console. By redirecting the StandardOutput stream, you can manipulate or suppress the output of a process.

To use StandardOutput, you must set ProcessStartInfo.UseShellExecute to false, and set ProcessStartInfo.RedirectStandardOutput to true. Otherwise, reading from the StandardOutput stream throws an exception.

The redirected StandardOutput stream can be read synchronously or asynchronously. Methods such as Read, ReadLine, and ReadToEnd perform synchronous read operations on the output stream of the process. These synchronous read operations do not complete until the associated Process writes to its StandardOutput stream, or closes the stream.

In contrast, BeginOutputReadLine starts asynchronous read operations on the StandardOutput stream. This method enables a designated event handler for the stream output and immediately returns to the caller, which can perform other work while the stream output is directed to the event handler.

Deadlock problem

Synchronous read operations introduce a dependency between the caller reading from the StandardOutput stream and the child process writing to that stream.

Case 1. A deadlock condition may result if the parent process calls p.WaitForExit before p.StandardOutput.ReadToEnd. In the case the child process writes enough text to fill the redirected stream, the parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full StandardOutput stream.


Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();

// To avoid deadlocks, always read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Case 2. The code example avoids the deadlock condition by performing asynchronous read operations on the StandardOutput stream. A deadlock condition results if the parent process calls p.StandardOutput.ReadToEnd followed by p.StandardError.ReadToEnd and the child process writes enough text to fill its error stream. The parent process would wait indefinitely for the child process to close its StandardOutput stream. The child process would wait indefinitely for the parent to read from the full StandardError stream.

Alternately, you can avoid the deadlock condition by creating two threads and reading the output of each stream on a separate thread.


// To avoid deadlocks, use asynchronous read operations on at least one of the streams.
// Do not perform a synchronous read to the end of both redirected streams.
p.BeginOutputReadLine();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();

A fantastic solution for both cases. Stackoverflow. wcfNote: in the SO discussion, the code may throw unhandled ObjectDisposedException. Cause: if the process continues to output data after the timeout has been exceeded and then terminates, the outputWaitHandle and errorWaitHandle variables will be accessed after being disposed.


using System.Threading; // For AutoResetEvent
using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();

    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
    {
        process.OutputDataReceived += (sender, e) => {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        };

        process.Start();

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        if (process.WaitForExit(timeout) &&
            outputWaitHandle.WaitOne(timeout) &&
            errorWaitHandle.WaitOne(timeout))
        {
            // Process completed. Check process.ExitCode here.
        }
        else
        {
            // Timed out.
        }
    }
}


using System;
using System.Diagnostics;
using System.ComponentModel;

namespace MyProcessSample
{
    class MyProcess
    {
        // Opens the Internet Explorer application.
        void OpenApplication(string myFavoritesPath)
        {
            // Start Internet Explorer. Defaults to the home page.
            Process.Start("IExplore.exe");

            // Display the contents of the favorites folder in the browser.
            Process.Start(myFavoritesPath);
        }

        // Opens urls and .html documents using Internet Explorer.
        void OpenWithArguments()
        {
            // url's are not considered documents. They can only be opened
            // by passing them as arguments.
            Process.Start("IExplore.exe", "www.northwindtraders.com");

            // Start a Web page using a browser associated with .html and .asp files.
            Process.Start("IExplore.exe", "C:\\myPath\\myFile.htm");
            Process.Start("IExplore.exe", "C:\\myPath\\myFile.asp");
        }

        // Uses the ProcessStartInfo class to start new processes,
        // both in a minimized mode.
        void OpenWithStartInfo()
        {
            ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
            startInfo.WindowStyle = ProcessWindowStyle.Minimized;

            Process.Start(startInfo);

            startInfo.Arguments = "www.northwindtraders.com";

            Process.Start(startInfo);
        }

        static void Main()
        {
            // Get the path that stores favorite links.
            string myFavoritesPath =
                Environment.GetFolderPath(Environment.SpecialFolder.Favorites);

            MyProcess myProcess = new MyProcess();

            myProcess.OpenApplication(myFavoritesPath);
            myProcess.OpenWithArguments();
            myProcess.OpenWithStartInfo();
        }
    }
}

/////////////// Another example

public bool PrintPDF (string ghostScriptPath, int numberOfCopies, string printerName, string pdfFileName)
{
    ProcessStartInfo startInfo  = new ProcessStartInfo();
    startInfo.Arguments         = " -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=" + Convert.ToString(numberOfCopies) + " -sDEVICE=ljet4 -sOutputFile=\"\\\\spool\\" + printerName + "\" \"" + pdfFileName + "\" ";
    startInfo.FileName          = ghostScriptPath; 
    startInfo.UseShellExecute = false;  // whether to use the operating system shell to start the process.

    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;

    Process process = Process.Start(startInfo);

    Console.WriteLine( process.StandardError.ReadToEnd() + process.StandardOutput.ReadToEnd() );

    process.WaitForExit(30000);
    if (process.HasExited == false) process.Kill();

    return process.ExitCode == 0;
}

CloseMainWindow()

Process.CloseMainWindow() closes a process that has a user interface by sending a close message to its main window.

You can call Kill() and CloseMainWindow() only for processes that are running on the local computer. You cannot cause processes on remote computers to exit. You can view information for processes running on remote computers though.

MSDN.


using System;
using System.Diagnostics;
using System.Threading;

namespace Process_Sample
{
   class MyProcessClass
   {
      public static void Main()
      {
         try
         {
            Process myProcess;
            myProcess = Process.Start("Notepad.exe");
            // Display physical memory usage 5 times at intervals of 2 seconds.
            for (int i = 0;i < 5; i++)
            {
               if (!myProcess.HasExited)
               {
                   // Discard cached information about the process.
                   myProcess.Refresh();
                   // Print working set to console.
                   Console.WriteLine("Physical Memory Usage: " 
                                        + myProcess.WorkingSet.ToString());
                   // Wait 2 seconds.
                   Thread.Sleep(2000);
               }
               else {
                   break;
               } 
            }

            // Close process by sending a close message to its main window.
            myProcess.CloseMainWindow();
            // Free resources associated with process.
            myProcess.Close();

         }
         catch(Exception e)
         {
            Console.WriteLine("The following exception was raised: ");
            Console.WriteLine(e.Message);
         }
      }
   }
}

Starting process on ASP.NET

MSDN.

ASP.NET Web page and server control code executes in the context of the ASP.NET worker process on the Web server. If you use the Start method in an ASP.NET Web page or server control, the new process executes on the Web server with restricted permissions. The process does not start in the same context as the client browser, and does not have access to the user desktop.

Environment

MSDN: environment.

GetEnvironmentVariable(String) method is equivalent to calling the GetEnvironmentVariable(String, EnvironmentVariableTarget.Process). The environment block of the current process includes the following environment variables:

Environment variable names are not case-sensitive.


using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      // Change the directory to %WINDIR%
      Environment.CurrentDirectory = Environment.GetEnvironmentVariable("windir");
      DirectoryInfo info = new DirectoryInfo(".");

      Console.WriteLine("Directory Info:   " + info.FullName);
   }
}

// The example displays output like the following:
//        Directory Info:   C:\windows

MarshalByRefObject

Enables access to objects across application domain boundaries in applications that support remoting.

Remoting means call between AppDomains or machines. Microsoft now recommends WCF instead of remoting. Objects that do not inherit from MarshalByRefObject are implicitly marshal by value. When a remote application references a marshal by value object, a copy of the object is passed across application domain boundaries. MarshalByRefObject objects are accessed directly within the boundaries of the local application domain. The first time an application in a remote application domain accesses a MarshalByRefObject, a proxy is passed to the remote application. Subsequent calls on the proxy are marshaled back to the object residing in the local application domain. Assembly: Mscorlib.

Net

HttpClient

Namespace: System.Net.Http.

asp.net: calling a web API from a NET client.


using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace ProductStoreClient
{
    class Product
    {
        public string Name { get; set; }
        public double Price { get; set; }
        public string Category { get; set; }
    }

    class Program
    {
        static void Main()
        {
            RunAsync().Wait(); // Blocks until RunAsync completes.
            // It's OK to block the main thread in a console application, but in a GUI application, you should never block the UI thread.
        }

        static async Task RunAsync()
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:9000/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // HTTP GET
                HttpResponseMessage response = await client.GetAsync("api/products/1");
                if (response.IsSuccessStatusCode)
                {
                    Product product = await response.Content.ReadAsAsync<Product>();
                    Console.WriteLine("{0}\t${1}\t{2}", product.Name, product.Price, product.Category);
                }

                // HTTP POST
                var gizmo = new Product() { Name = "Gizmo", Price = 100, Category = "Widget" };
                response = await client.PostAsJsonAsync("api/products", gizmo);
                // wcfNote: PostAsJsonAsync needs "System.Net.Http.Formatting.Extension" in NuGet, and it's in System.Net.Http.Formatting.
                if (response.IsSuccessStatusCode)
                {
                    Uri gizmoUrl = response.Headers.Location;

                    // HTTP PUT
                    gizmo.Price = 80;   // Update price
                    response = await client.PutAsJsonAsync(gizmoUrl, gizmo);

                    // HTTP DELETE
                    response = await client.DeleteAsync(gizmoUrl);
                }
            }
        }
    }
}

Post XML

PostAsync XML.


using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

using WechatComm.WechatEvents;

namespace ConsoleHostTest
{
    [TestClass]
    public class EventsPostTest
    {
        static async Task TestSubscribeAsync()
        {
            using (var client = new HttpClient())
            {
                var testURI = "http://localhost:3000/";
                var modulePath = "test/events";

                client.BaseAddress = new Uri(testURI);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

                // HTTP POST
                var msg = new SubscribeEvent()
                {
                    ToUserName = "to",
                    FromUserName = "from",
                    CreateTime = (int)DateTime.Now.ToBinary(),
                    MsgType = "event",
                    Event = "subscribe",
                    EventKey = "123456",
                    Ticket = "http://haha"
                };

                var msgXml = string.Empty;
                using (var sww = new StringWriter())
                using (var writer = XmlWriter.Create(sww))
                {
                    var s = new XmlSerializer(typeof(SubscribeEvent));
                    s.Serialize(writer, msg);
                    msgXml = sww.ToString();
                }

                HttpResponseMessage response = await client.PostAsync(modulePath, new StringContent(msgXml, Encoding.UTF8, "application/xml"));
                if (response.IsSuccessStatusCode)
                {
                    Uri responseLoc = response.Headers.Location;
                    Console.WriteLine("Response location: {0}", responseLoc);
                }
            }
        }

        [TestMethod]
        public void TestSubscribe()
        {
            TestSubscribeAsync().Wait();
        }
    }
}
Exception: xmlns not expected

Exception: xmlns not expected. SO: deserialize XML without namespace.


// Standard XML.

<?xml version="1.0" encoding="utf-16"?>
<SubscribeEvent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ToUserName>to</ToUserName>
  <FromUserName>from</FromUserName>
  <CreateTime>813221011</CreateTime>
  <MsgType>event</MsgType>
  <Event>subscribe</Event>
  <EventKey>123456</EventKey>
  <Ticket>http://haha</Ticket>
</SubscribeEvent>

// Wechat XML. Not so standard.

<xml>
  <ToUserName>to</ToUserName>
  <FromUserName>from</FromUserName>
  <CreateTime>813221011</CreateTime>
  <MsgType>event</MsgType>
  <Event>subscribe</Event>
  <EventKey>123456</EventKey>
  <Ticket>http://haha</Ticket>
</xml>

To handle with Wechat XMl, you have to manually set XmlRoot:


[Serializable, XmlRoot(ElementName = "xml", Namespace = "")]
public class BaseEvent
{
    public string ToUserName; // 开发者微信号
    public string FromUserName; // 发送方帐号(一个OpenID)
    public int CreateTime; // 消息创建时间 (整型)
    public string MsgType; // 消息类型,event
    public string Event; // 事件类型
}

[Serializable, XmlRoot(ElementName = "xml", Namespace = "")]
public class SubscribeEvent : BaseEvent
{
    public string EventKey; // 事件KEY值,qrscene_为前缀,后面为二维码的参数值
    public string Ticket; // 二维码的ticket,可用来换取二维码图片
}
Exception: There is no Unicode byte order mark

Exception: There is no Unicode byte order mark. Cannot switch to Unicode. See SO. Solution: remove encoding attribute from XML.


// Replace
<?xml version="1.0" encoding="utf-16"?>
with
// <?xml version="1.0"?>

HTTP Request methods

SO: http request with post.

There are several ways to perform GET and POST requests:


// Method 1: Legacy

using System.Net;
using System.Text;  // for class Encoding

// POST

var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");
var postData = "thing1=hello";
    postData += "&thing2=world";
var data = Encoding.ASCII.GetBytes(postData);

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded"; // request.ContentType = "application/json";
request.ContentLength = data.Length;

using (var stream = request.GetRequestStream())
{
    stream.Write(data, 0, data.Length);
}

var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

// GET

var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

// Method 2: WebClient (Also now legacy)

using System.Net;
using System.Collections.Specialized;

// POST

using (var client = new WebClient())
{
    var values = new NameValueCollection();
    values["thing1"] = "hello";
    values["thing2"] = "world";

    var response = client.UploadValues("http://www.example.com/recepticle.aspx", values);

    var responseString = Encoding.Default.GetString(response);
}

// GET

using (var client = new WebClient())
{
    var responseString = client.DownloadString("http://www.example.com/recepticle.aspx");
}

// Method 3: HttpClient
// Currently the preferred approach. Asynchronous. Ships with .NET 4.5; portable version for other platforms available via NuGet.

using System.Net.Http;

// POST

using (var client = new HttpClient())
{
    var values = new Dictionary<string, string>
    {
       { "thing1", "hello" },
       { "thing2", "world" }
    };
    var content = new FormUrlEncodedContent(values);

    var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
    var responseString = await response.Content.ReadAsStringAsync();
}

// GET

using (var client = new HttpClient())
{
    var responseString = client.GetStringAsync("http://www.example.com/recepticle.aspx");
}

// Method 4: 3rd-Party Libraries

// RestSharp
// Tried and tested library for interacting with REST APIs. Portable. Available via NuGet.

// Flurl.Http
// Newer library sporting a fluent API and testing helpers. HttpClient under the hood. Portable. Available via NuGet.

using Flurl.Http;

// POST

var responseString = await "http://www.example.com/recepticle.aspx"
    .PostUrlEncodedAsync(new { thing1 = "hello", thing2 = "world" })
    .ReceiveString();

// GET

var responseString = await "http://www.example.com/recepticle.aspx"
    .GetStringAsync();

STAThreadAttribute

MSDN: STAThreadAttribute.

Indicates that the COM threading model for an application is single-threaded apartment (STA).

Apply this attribute to the entry point method (the Main() method in C# and Visual Basic). It has no effect on other methods.

SO: what does STAThread do.

The STAThreadAttribute is essentially a requirement for the Windows message pump to communicate with COM components. Although core Windows Forms does not use COM, many components of the OS such as system dialogs do use this technology.

STAThreadAttribute indicates that the COM threading model for the application is single-threaded apartment. This attribute must be present on the entry point of any application that uses Windows Forms; if it is omitted, the Windows components might not work correctly. If the attribute is not present, the application uses the multithreaded apartment model, which is not supported for Windows Forms.

See more on how the threading model works at the CLR level.

SO: STA and MTA.

The COM threading model is called an "apartment" model, where the execution context of initialized COM objects is associated with either a single thread (Single Thread Apartment) or many threads (Multi Thread Apartment). In this model, a COM object, once initialized in an apartment, is part of that apartment for the duration of it's runtime.

The STA model is used for COM objects that are not thread safe. That means they do not handle their own synchronization. A common use of this is a UI component. So if another thread needs to interact with the object (such as pushing a button in a form) then the message is marshalled onto the STA thread. The windows forms message pumping system is an example of this.

If the COM object can handle its own synchronization then the MTA model can be used where multiple threads are allowed to interact with the object without marshalled calls.

TypeInitializationException

The exception is thrown as a wrapper around the exception thrown by the class initializer.

When a class initializer fails to initialize a type, a TypeInitializationException is created and passed a reference to the exception thrown by the type's class initializer. The InnerException property of TypeInitializationException holds the underlying exception.

Typically, the TypeInitializationException exception reflects a catastrophic condition (the runtime is unable to instantiate a type) that prevents an application from continuing. Most commonly, the TypeInitializationException is thrown in response to some change in the executing environment of the application. Consequently, other than possibly for troubleshooting debug code, the exception should not be handled in a try/catch block. Instead, the cause of the exception should be investigated and eliminated.

Threading

Tasks

Start()

MSDN: FAQ on task Start() is a good article explaining the mechanism behind Start(). In summary:


var t = Task.Factory.StartNew(someDelegate);

// is functionally equivalent to:

var t = new Task(someDelegate);
t.Start();

StartNew() is slightly more efficient, because it knows that no one else could be starting the Task concurrently, so it doesn’t need to employ any synchronization.

Start() is useful in the following case:


Task theTask = null;
theTask = Task.Run(() => Console.WriteLine(“My ID is {0}.”, theTask.Id));

// Spot the flaw: There’s a race.
// During the call to Task.Run, a new Task object is created and is queued to the ThreadPool scheduler.  If there’s not that much going on in the ThreadPool, a thread from the pool might pick it up almost instantly and start running it.  That thread is now racing to access the variable ‘theTask’ with the main thread that called Task.Run and that needs to store the created Task into that ‘theTask’ variable.

// Fix this race by separating the construction and scheduling:
Task theTask = null;
theTask = new Task(() =>Console.WriteLine(“My ID is {0}.”, theTask.Id));
theTask.Start(TaskScheduler.Default);

Xml

SO.


public static bool SerializeXml<T>(T value, ref string serializeXml)
{
    if (value == null)
    {
        return false;
    }
    try
    {
        XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
        StringWriter stringWriter = new StringWriter();
        XmlWriter writer = XmlWriter.Create(stringWriter);

        xmlserializer.Serialize(writer, value);

        serializeXml = stringWriter.ToString();

        writer.Close();
        return true;
    }
    catch (Exception ex)
    {
        return false;
    }
}