0

My code:

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

  public class Program
  {
    private static void Main(string[] args)
    {
      var test = new Test();    // TypeInitializationException?
      var test2 = new Test();
    }

    public class Test
    {
      public Test()
      {
        Trace.WriteLine("Test Created");
      }

      static Test()
      {
        Task.Factory.StartNew(
                    () =>
                    {
                      throw new Exception();
                    });
      }
    }
  }

If I change the static const to :

  static Test()
          {
              throw new Exception();
          }

Then it is throwing TypeInitializationException! I thought static constructor is thread safe?

Is the C# static constructor thread safe?


private static void Main(string[] args)
    {


      Task.Factory.StartNew(
                        () =>
                        {
                          var test = new Test();
                        });

      var test2 = new Test(); // HERE I GET THE EXCEPTION!!!!
    }

    public class Test
    {
      public Test()
      {
        Trace.WriteLine("Test Created");
      }

      static Test()
      {
        throw new Exception();
      }
    }
  }
Community
  • 1
  • 1
Bassam Alugili
  • 16,345
  • 7
  • 52
  • 70
  • What does thread safety has to do in your code ? – user2711965 Apr 30 '14 at 15:52
  • 1
    Are you wondering why the _first_ example _doesn't_ throw a `TypeInitializationException`? – D Stanley Apr 30 '14 at 15:54
  • The exception is thrown in other thread and my code working without problem! If I create the Test class in a Task and I throw the exception in the Task with my second const then I get everywhere for all threads TypeInitializationException – Bassam Alugili Apr 30 '14 at 15:56
  • possible duplicate of [Is the C# static constructor thread safe?](http://stackoverflow.com/questions/7095/is-the-c-sharp-static-constructor-thread-safe) – Black Frog Apr 30 '14 at 16:00
  • It sounds like you expect exceptions to be observable between threads. That's not the case. – Brian Rasmussen Apr 30 '14 at 16:02

3 Answers3

4

Thread-safe in this context only means that you don't need to worry about two threads invoking the static constructor at the same time, or one thread starting the static constructor, and a second thread thinking it has run and skipping the constructor, even though it hasn't finished (causing access to uninitialized fields).

If you throw an exception in the constructor, that is simply an error. Nothing to do with thread safety. Type initialization errors are very bad, and will keep happening until the static constructor can successfully complete.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
4

Thread safe is not a particularly helpful phrase to use. You should generally avoid using it as it doesn't really tell you what operations are and are not safe.

Instead it's important to specifically state what thread-related operations and situations are supported in any given context. One can then objectively and clearly state whether the expectations are violated.

C# will ensure that static constructors are run at some point before they are used, no matter how many threads might use the class, or whether another thread is currently running the static constructor.

C# will ensure that it doesn't run the static constructor more than once, no matter how many different threads might be using the same class at around the same time, or whether another thread uses a class while it is currently being initialized.

The specs specifically state that if a static constructor throws an exception in the one time that it runs then all future uses of that type will throw a TypeInitializationException, which is what you are seeing.

The behavior that you are seeing is entirely in line with the behavior defined in the specifications.

Servy
  • 202,030
  • 26
  • 332
  • 449
1

Static constructor wraps all exceptions which are thrown inside into TypeInitializationException and that doesn't have relation to thread safety.

It is guaranteed that constructor is executed once and only once, before first usage of a type (or no execution if type isn't used) not depending on how many threads access the type. This means it is thread safe.

Sasha
  • 8,537
  • 4
  • 49
  • 76
  • Well, it depends on your view point. [This demonstrates](http://blogs.msdn.com/b/pfxteam/archive/2011/05/03/10159682.aspx) static constructors are not thread safe. – oleksii Apr 30 '14 at 16:06
  • 1
    @oleksii As per my answer, one should avoid using terms like "thread safe". There are certain guarantees about static constructors that the C# language ensures. They are met. Are there ways to write programs, given those constraints, that do things that you may not want. Yes. That's true of any possible implementation. No matter what you could possibly implement, there is always some way of writing a program that won't behave as expected, because it expects guarantees not there. – Servy Apr 30 '14 at 16:17
  • @Servy That sounds like some programming philosophy in the style of Turing theorems =). But sounds good. – Sasha Apr 30 '14 at 16:29