Как определить многопоточное использование?

Достаточно ли сравнивать ManagedThreadId во время создания объекта и во время вызова метода для проверки того, что он не используется в сценарии многопоточности?

public class SingleThreadSafe
{
    private readonly int threadId;
    public SingleThreadSafe()
    {
        threadId = Thread.CurrentThread.ManagedThreadId;
    }

    public void DoSomethingUsefulButNotThreadSafe()
    {
        if(threadId!=Thread.CurrentThread.ManagedThreadId)
        {
            throw new InvalidOperationException(
                "This object is being accessed by a thread different than the one that created it. " +
                " But no effort has been made to make this object thread safe.");
        }
        //Do something useful, like use a previously established DbConnection
    }
}

Моя интуиция часто ошибается в потоковом режиме, поэтому я хотел проверить, есть ли крайние случаи, о которых я должен помнить.

Ответ 1

Нет, этого недостаточно.

Идентификатор управляемого потока может повторно использоваться CLR, поэтому if(threadId!=Thread.CurrentThread.ManagedThreadId) может возвращать false, даже если вызывающий поток отличается от того, который используется для построения объекта.

То, что вы пытаетесь достичь, возможно путем сравнения ссылок:

if (!object.ReferenceEquals(Thread.CurrentThread, ThreadThatCreatedThis))
// ...

ИЗМЕНИТЬ:

MSDN говорит, однако, что:

Значение свойства ManagedThreadId не изменяется со временем, даже если неуправляемый код, на котором размещается среда выполнения общего языка, реализует поток как волокно.

http://msdn.microsoft.com/en-us/library/system.threading.thread.managedthreadid%28v=vs.110%29.aspx

Ответ 2

Это в основном то, что делает Windows Forms. Вот фрагмент из Control.InvokeRequired (цитируется из справочного источника ):

public bool InvokeRequired {
    get {
        using (new MultithreadSafeCallScope())
        {
            ...
            int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(hwnd, out pid);
            int currentThread = SafeNativeMethods.GetCurrentThreadId();
            return(hwndThread != currentThread);
        }
    }
}

Если сравнивать идентификаторы потоков достаточно хорошо для Windows Forms, я полагаю, это было бы достаточно для меня...