Делегаты C#, ссылочное время разрешения

У меня есть простой вопрос о делегатах .NET. Скажите, что у меня есть что-то вроде этого:

    public void Invoke(Action<T> action)
    {
        Invoke(() => action(this.Value));
    }

    public void Invoke(Action action)
    {
        m_TaskQueue.Enqueue(action);
    }

Первая функция включает ссылку на this.Value. Во время времени выполнения, когда первое, метод с универсальным параметром назовут, он обеспечит this.Value так или иначе к второму, но как? Они вошли в мой ум:

  • Вызов по значению (структура) - текущее значение this.Value передается, поэтому если m_TaskQueue выполняет его 5 минут спустя, значение не будет в его недавнем состоянии, это будет тем, чем это было при первой ссылке.
  • Вызов по ссылке (ссылочный тип) - затем новое состояние Value будет ссылаться во время выполнения действия, но если я изменяюсь this.Value к другой ссылке перед выполнением действия это будет все еще указывать на старую ссылку
  • Вызов по имени (оба) - где this.Value будет оценен, когда действие назовут. Я полагаю, что фактическая реализация содержала бы ссылку на this затем оцените Value на этом во время фактической казни делегата с тех пор нет никакого вызова по имени.

Я предполагаю, что это было бы Вызовом стиля имени, но не могло найти документацию настолько задающейся вопросом, если это - четко определенное поведение. Этот класс - что-то как Агент в Scala или Erlang, таким образом, мне нужен он, чтобы быть ориентированным на многопотоковое исполнение. Я не хочу Invoke функция для разыменования Value сразу, это будет сделано в безопасном потоке для this объект m_TaskQueue.

7
задан Vikrant 2 November 2016 в 12:44
поделиться

3 ответа

Vireshark фактически использует Winpcap для этого, и, как показывает другой ответ, вы также можете использовать его.

Можно также использовать класс System.Net.Sockets.Socket и перевести его в неразборчивый режим. Я использую это для захвата IP-трафика (например, TCP и UDP) из данного сетевого интерфейса. Вот пример.

using System.Net;
using System.Net.Sockets;

Socket socket =
    new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(IPAddress.Parse("X.X.X.X"), 0)); // specify IP address
socket.ReceiveBufferSize = 2 * 1024 * 1024; // 2 megabytes
socket.ReceiveTimeout = 500; // half a second
byte[] incoming = BitConverter.GetBytes(1);
byte[] outgoing = BitConverter.GetBytes(1);
socket.IOControl(IOControlCode.ReceiveAll, incoming, outgoing);

После создания и настройки сокета можно использовать метод Receive () для начала получения данных. При каждом вызове Receive () возвращаемый буфер будет содержать IP-пакет. См. здесь для разбивки заголовка IPv4, здесь для заголовка UDP и здесь для заголовка TCP. Если поле Protocol заголовка IP содержит значение 17, то имеется пакет UDP.

ПРИМЕЧАНИЕ Необработанные сокеты в Windows требуют наличия администратора в локальной системе. Следующий язык содержится в статье MSDN .

Использование разъема типа SOCK_RAW требует административных привилегий. Пользователи, использующие приложения Winsock которые используют необработанные сокеты, должны быть членами группы администраторов на локальный компьютер, в противном случае необработанный сокет вызовы завершатся неуспешно с кодом ошибки WSAEACCES. В Windows Vista и более поздних версиях доступ для необработанных сокетов применяется в создание сокета. В более ранних версиях Windows, доступ для необработанных сокетов принудительно во время другого сокета операции.

-121--2681487-

Мои мысли:

  1. Вероятно, это означает «идти».
  2. Postgresql также использует\g в качестве терминатора оператора. Postgresql старше MySQL, так что это могло повлиять на них.

Но, как я указал в своем комментарии к посту Андриева выше, это на самом деле делает верхний регистр, который заставляет дисплей располагаться вертикально. Нижний регистр\g не имеет такого эффекта, или если он имеет, то в документации его не упоминается. (У меня нет установки MySQL, которую можно было бы опробовать.)

-121--1607234-

Позвольте мне ответить на ваш вопрос, описав, какой код мы на самом деле генерируем для этого. Я переименую ваш запутанно названный другой метод Invoke; нет необходимости понимать, что здесь происходит.

Предположим, что вы сказали

class C<T>
{
  public T Value;
  public void Invoke(Action<T> action) 
  { 
      Frob(() => action(this.Value)); 
  } 
  public void Frob(Action action) 
  {  // whatever
  } 
}

Компилятор генерирует код, как будто вы на самом деле написали:

class C<T>
{
  public T Value;

  private class CLOSURE
  {
     public Action<T> ACTION;
     public C<T> THIS;
     public void METHOD()
     {
       this.ACTION(this.THIS.Value);
     }
  }

  public void Invoke(Action<T> action) 
  { 
      CLOSURE closure = new CLOSURE();
      closure.THIS = this;
      closure.ACTION = action;
      Frob(new Action(closure.METHOD)); 
  } 
  public void Frob(Action action) 
  {  // whatever
  } 
}

Это отвечает на ваш вопрос?

19
ответ дан 6 December 2019 в 05:55
поделиться

Главное - помнить, что область видимости является лексической; это то, о чем позаботится компилятор. Таким образом, он захватывает переменных , а не их значения . Другой вопрос, являются ли эти значения типами значений или ссылочными типами.

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

var myVariable = "something";
Action a = () => Console.WriteLine(myVariable);
myVariable = "something else entirely"
a();

выводит «что-то совершенно другое». В этом свете не имеет значения, сколько раз вы оборачиваете, сохраняете или перемещаете функцию; он по-прежнему относится к включенной в него переменной. Итак, короче говоря, важно значение заключенной переменной при фактическом выполнении делегата.

4
ответ дан 6 December 2019 в 05:55
поделиться

Делегат сохраняет ссылку на переменную, а не ее значение. Если вы хотите сохранить текущее значение (при условии, что это тип значения), вам необходимо сделать его локальную копию:

public void Invoke(Action<T> action)
{
    var localValue = this.Value;
    Invoke(() => action(localValue));
}

Если это изменяемый ссылочный тип, вы можете сделать локальную копию / глубокую копию.

8
ответ дан 6 December 2019 в 05:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: