C #: использование RegisterWaitForSingleObject, если операция завершается первой

Я делаю асинхронный сетевой ввод-вывод, используя методы стиля Begin /End. (На самом деле это запрос к хранилищу таблиц Azure, но я не думаю, что это имеет значение.) Я реализовал тайм-аут на стороне клиента, используя ThreadPool.RegisterWaitForSingleObject(). Насколько я могу судить, это работает нормально.

Поскольку ThreadPool.RegisterWaitForSingleObject() принимает WaitHandle в качестве аргумента я должен начать операцию ввода-вывода, затем выполнить ThreadPool.RegisterWaitForSingleObject(). Похоже, что это дает возможность завершить ввод-вывод еще до того, как я зарегистрирую ожидание.

Упрощенный пример кода:

private void RunQuery(QueryState queryState)
{
    //Start I/O operation
    IAsyncResult asyncResult = queryState.Query.BeginExecuteSegmented(NoopAsyncCallback, queryState);

    //What if the I/O operation completes here? 

    queryState.TimeoutWaitHandle = ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, QuerySegmentCompleted, asyncResult, queryTimeout, true);
}

private void QuerySegmentCompleted(object opState, bool timedOut){
    IAsyncResult asyncResult = opState as IAsyncResult;
    QueryState state = asyncResult.AsyncState as QueryState;

    //If the I/O completed quickly, could TimeoutWaitHandle could be null here?
    //If so, what do I do about that?
    state.TimeoutWaitHandle.Unregister(asyncResult.AsyncWaitHandle);
}

Какой правильный способ справиться с этим? Мне по-прежнему нужно беспокоиться о Unregister() в AsyncWaitHandle? Если да, то есть ли достаточно простой способ дождаться его установки?

7 голосов | спросил Brian Reischl 24 Maypm12 2012, 20:34:10

2 ответа


0

Да, у вас и у всех есть эта проблема. И это не имеет значения, если IO завершен синхронно или нет. Между обратным вызовом и назначением все еще есть гонка. Microsoft должна была автоматически предоставить RegisteredWaitHandle для этой функции обратного вызова. Это решило бы все. Да ладно, задним числом всегда 20-20, как говорится.

Что вам нужно сделать, так это продолжать читать переменную RegisteredWaitHandle, пока она не станет нулевой. Это нормально делать в тесной петле, потому что гонка достаточно тонкая, чтобы петля не вращалась очень много раз.

private void RunQuery(QueryState queryState)
{
  // Start the operation.
  var asyncResult = queryState.Query.BeginExecuteSegmented(NoopAsyncCallback, queryState);

  // Register a callback.
  RegisteredWaitHandle shared = null;
  RegisteredWaitHandle produced = ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle,
    (state, timedout) =>
    {
      var asyncResult = opState as IAsyncResult;
      var state = asyncResult.AsyncState as QueryState;
      while (true)
      {
        // Keep reading until the value is no longer null.
        RegisteredWaitHandle consumed = Interlocked.CompareExchange(ref shared, null, null);
        if (consumed != null)
        {
          consumed.Unregister(asyncResult.AsyncWaitHandle);
          break;
        }
      }
    }, asyncResult, queryTimeout, true);

  // Publish the RegisteredWaitHandle so that the callback can see it.
  Interlocked.CompareExchange(ref shared, produced, null);
}
ответил Brian Gideon 24 Maypm12 2012, 23:00:44
0

Вам не нужно отменять регистрацию, если ввод-вывод завершен до истечения времени ожидания, поскольку именно завершение сигнализировало о вашем обратном вызове. Фактически, после прочтения документов метода отмены регистрации, кажется совершенно ненужным вызывать его, поскольку вы выполняете только один раз, и вы не отменяете регистрацию в несвязанном методе.

http://msdn.microsoft.com/ан-нас /библиотека /system.threading.registeredwaithandle.unregister.aspx

  

Если метод обратного вызова выполняется во время выполнения Unregister, waitObject не сигнализируется до тех пор, пока метод обратного вызова не завершится. В частности, если метод обратного вызова выполняет Unregister, waitObject не передается, пока этот метод обратного вызова не завершится.

ответил Slugart 24 Maypm12 2012, 20:58:15

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132