Странно, если условие, сгенерированное рефлектором
Время от времени я буду писать программу, чтобы напомнить себе о чем-то, и вот одна из них, которую я писал вчера, когда случилось что-то странное.
Первоначальный источник
using System;
using System.Threading;
namespace TestThreadFunctions
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.Name = "Main thread";
var t = JoiningAnAlreadyCompletedThread();
JoiningIsIdempotent(t);
Console.ReadKey();
}
static Thread JoiningAnAlreadyCompletedThread()
{
Thread t = new Thread(() =>
{
Console.WriteLine($"{Thread.CurrentThread.Name} ({Thread.CurrentThread.ManagedThreadId}): I'm done now.\n");
})
{ Name = "Worker 1" };
t.Start();
// Give a long time-out so we know that the
// current thread did not wait the entire time-out
// or that it didn't wait at all because the thread
// we are joining on has already completed.
t.Join(10000);
Console.WriteLine($"{Thread.CurrentThread.Name} ({Thread.CurrentThread.ManagedThreadId}): I just joined on another thread that I knew was already completed even before I joined. See nothing happened. .NET doesn't punish you for joining a thread that has already completed, unlike POSIX systems, which do.\n");
return t;
}
static void JoiningIsIdempotent(Thread threadToJoinOn)
{
Console.WriteLine($"{Thread.CurrentThread.Name} ({Thread.CurrentThread.ManagedThreadId}): I am about to join a thread that I already joined with earlier. I want to see if joining is idempotent.\n");
// Joining is idempotent
threadToJoinOn.Join();
Console.WriteLine($"{Thread.CurrentThread.Name} ({Thread.CurrentThread.ManagedThreadId}): I just finished joining with a thread that I already joined with earlier. See! nothing happened. Joining is idempotent.\n");
}
}
}
Когда я посмотрел программу в Reflector, это было странно if
состояние в начале JoiningAnAlreadyCompletedThread
метод вроде так:
private static Thread JoiningAnAlreadyCompletedThread()
{
if (<>c.<>9__1_0 == null)
{
ThreadStart start1 = <>c.<>9__1_0;
}
...
}
Я прочитал это пару раз, чтобы подтвердить, что я ничего не пропустил. Это так странно, что ничего не делает.
Просто для полноты, вот полностью декомпилированная программа от Reflector.
Отраженный источник
internal class Program
{
// Methods
private static Thread JoiningAnAlreadyCompletedThread()
{
if (<>c.<>9__1_0 == null)
{
ThreadStart start1 = <>c.<>9__1_0;
}
Thread thread1 = new Thread(<>c.<>9__1_0 = new ThreadStart(<>c.<>9.<JoiningAnAlreadyCompletedThread>b__1_0)) {
Name = "Worker 1"
};
Thread t = thread1;
t.Start();
t.Join(0x2710);
Console.WriteLine(string.Format("{0} ({1}): I just joined on another thread that I knew was already completed even before I joined. See nothing happened. .NET doesn't punish you for joining a thread that has already completed, unlike POSIX systems, which do.\n", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId));
return t;
}
private static void JoiningIsIdempotent(Thread threadToJoinOn)
{
Console.WriteLine(string.Format("{0} ({1}): I am about to join a thread that I already joined with earlier. I want to see if joining is idempotent.\n", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId));
threadToJoinOn.Join();
Console.WriteLine(string.Format("{0} ({1}): I just finished joining with a thread that I already joined with earlier. See! nothing happened. Joining is idempotent.\n", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId));
}
private static void Main(string[] args)
{
Thread.CurrentThread.Name = "Main thread";
JoiningIsIdempotent(JoiningAnAlreadyCompletedThread());
Console.ReadKey();
}
// Nested Types
[Serializable, CompilerGenerated]
private sealed class <>c
{
// Fields
public static readonly Program.<>c <>9 = new Program.<>c();
public static ThreadStart <>9__1_0;
// Methods
internal void <JoiningAnAlreadyCompletedThread>b__1_0()
{
Console.WriteLine(string.Format("{0} ({1}): I'm done now.\n", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId));
}
}
}
Я искал тот же источник в IL Spy, и он не делал ничего странного. Не было этого странного if
условие, которое ничего не делало.
IL Spy декомпилирован
// TestThreadFunctions.Program
private static Thread JoiningAnAlreadyCompletedThread()
{
ThreadStart arg_20_0;
if ((arg_20_0 = Program.<>c.<>9__1_0) == null)
{
arg_20_0 = (Program.<>c.<>9__1_0 = new ThreadStart(Program.<>c.<>9.<JoiningAnAlreadyCompletedThread>b__1_0));
}
Thread thread = new Thread(arg_20_0)
{
Name = "Worker 1"
};
thread.Start();
thread.Join(10000);
Console.WriteLine(string.Format("{0} ({1}): I just joined on another thread that I knew was already completed even before I joined. See nothing happened. .NET doesn't punish you for joining a thread that has already completed, unlike POSIX systems, which do.\n", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId));
return thread;
}
Так что, думаю, я не знаю, в чем тут вопрос. Может быть, это "почему Reflector сделал это?"
И тогда может быть ответ: "Ну, декомпиляция трудна", что я понимаю.
Итак, я действительно не знаю, в чем вопрос, но, думаю, я просто хотел поделиться своим недоумением.
Если вы действительно видите здесь вопрос, который имеет правдоподобное объяснение, я хотел бы знать, почему Reflector сделал это.
В противном случае я знаю, что этот вопрос будет опущен и закрыт.