Где параметры типа значения ref, хранящиеся для вызовов асинхронных методов в Microsoft CLR ?

Я понимаю, что это деталь реализации. Мне действительно любопытно, что это за деталь реализации в Microsoft CLR.

Теперь послушайте меня, поскольку я не изучал CS в колледже, поэтому я мог упустить некоторые фундаментальные принципы.

] Но мое понимание «стека» и «кучи», реализованных в CLR в ее нынешнем виде, я считаю твердым. Я не собираюсь делать какие-то неточные общие утверждения, например, вроде «типы значений хранятся в стеке». Но в наиболее распространенных сценариях - простые локальные переменные ванильного типа значения, либо передаются как параметры, либо объявляются внутри метода и не содержатся в закрытии - переменные типа значения хранятся в стеке (опять же, в Microsoft CLR).

Я догадываюсь, в чем я не уверен. здесь используются параметры типа ref .

Первоначально я думал, что если стек вызовов выглядит так (слева = внизу):

A() -> B() -> C()

... тогда локальная переменная, объявленная в рамках A и переданная как параметр ref в B , все еще может храниться в стеке - не так ли? B просто потребуется место в памяти, где эта локальная переменная хранилась в кадре A (простите меня, если это неправильная терминология; я думаю, ясно, что я имею в виду, тем не мение).

Я понял, что это не может быть строго правдой, когда мне пришло в голову, что я могу сделать это:

delegate void RefAction<T>(ref T arg);

void A()
{
    int x = 100;

    RefAction<int> b = B;

    // This is a non-blocking call; A will return immediately
    // after this.
    b.BeginInvoke(ref x, C, null);
}

void B(ref int arg)
{
    // Putting a sleep here to ensure that A has exited by the time
    // the next line gets executed.
    Thread.Sleep(1000);

    // Where is arg stored right now? The "x" variable
    // from the "A" method should be out of scope... but its value
    // must somehow be known here for this code to make any sense.
    arg += 1;
}

void C(IAsyncResult result)
{
    var asyncResult = (AsyncResult)result;
    var action = (RefAction<int>)asyncResult.AsyncDelegate;

    int output = 0;

    // This variable originally came from A... but then
    // A returned, it got updated by B, and now it's still here.
    action.EndInvoke(ref output, result);

    // ...and this prints "101" as expected (?).
    Console.WriteLine(output);
}

Итак, в приведенном выше примере, где x A область) хранится? А как это работает? Это в коробке? Если нет, подлежит ли он сейчас сборке мусора, несмотря на то, что он является типом значения? Или можно сразу же вернуть память?

Прошу прощения за многословный вопрос. Но даже если ответ будет довольно простым, возможно, это будет полезно для других, которые будут задумываться о том же в будущем.

5
задан Dan Tao 13 October 2010 в 18:21
поделиться