Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 136 стр.

UptoLike

gd, 1000, false
);
Thread.Sleep( 2500 );
ev.Set();
Console.ReadLine();
}
}
}
Приведенный пример демонстрирует использование периодического
вызова асинхронной процедуры – при регистрации делегата
(RegisterWaitForSingleObject) указывается максимальное время ожидания
1 секунда (1000 миллисекунд), после чего основной поток переводится в
состояние «спячки» на 2.5 секунды. За это время в очередь пула поступает
два вызова асинхронных процедур (с признаком вызова по тайм-ауту). Че-
рез 2.5 секунды основной поток пробуждается, переводит событие в сво-
бодное состояние, и в очередь пула поступает третий вызов. При обработ-
ке этого вызова регистрация делегата отменяется.
Последний способ связан с использованием методов BeginInvoke и
EndInvoke делегатов. Когда определяется какой-либо делегат функции, для
него будут определены методы: BeginInvoke (содержащий все аргументы
делегата плюс два дополнительных – AsyncCallback, который может быть
вызван по завершении обработки асинхронного вызова, и AsyncState, с
помощью которого можно определить состояние асинхронной процеду-
ры) и EndInvoke, содержащий все выходные параметры (т.е. описанные как
inout или out), плюс IAsyncResult, позволяющий узнать результат выпол-
нения процедуры.
Таким образом, использование BeginInvoke позволяет не только по-
ставить в очередь вызов асинхронной процедуры, но также связать с за-
вершением ее обработки еще один асинхронный вызов. Метод EndInvoke
служит для ожидания завершения обработки асинхронной процедуры:
using System;
using System.Threading;
namespace TestNamespace {
public class GreetingData {
private string m_greeting;
public GreetingData( string text ) { m_greeting = text; }
public static void Invoke( GreetingData arg ) {
Console.WriteLine( arg.m_greeting );
}
}
Разработка параллельных приложений для ОС Windows
259
При постановке в очередь асинхронного вызова можно указать объ-
ект, который является аргументом асинхронной процедуры (при создании
собственных потоков передача аргументов процедуре потока затрудни-
тельна).
Второй способ вызова асинхронных процедур связан с использованием
объектов, производных от класса System.Threading.WaitHandle (это события
и мьютексы). При этом вызов асинхронной процедуры связывается с пере-
водом объекта в свободное состояние. Данный метод может быть использо-
ван также для организации повторяющегося через определенные интервалы
вызова асинхронных процедур – при регистрации делегата указывается ма-
ксимальный интервал ожидания, и если он исчерпывается, то вызов разме-
щается в очереди пула, даже если объект остался занятым. Если объект по-
прежнему остается занятым, то вызов процедуры будет периодически разме-
щаться в очереди после исчерпания каждого интервала ожидания.
using System;
using System.Threading;
namespace TestNamespace {
class GreetingData {
private string m_greeting;
private RegisteredWaitHandle m_waithandle;
public GreetingData( string text ) { m_greeting = text; }
public void Invoke() { Console.WriteLine( m_greeting ); }
public RegisteredWaitHandle WaitHandle {
set {
if (value==null) m_waithandle.Unregister( null );
m_waithandle = value;
}
}
}
class TestApp {
static void AsyncProc( Object arg, bool isTimeout ) {
GreetingData gd = (GreetingData)arg;
if ( !isTimeout ) gd.WaitHandle = null;
gd.Invoke();
}
public static void Main() {
GreetingData gd = new GreetingData(“Hello”);
AutoResetEvent ev = new AutoResetEvent(false);
gd.WaitHandle=ThreadPool.RegisterWaitForSingleObject(
ev, new WaitOrTimerCallback(AsyncProc),
258
CIL и системное программирование в Microsoft .NET
258                         CIL и системное программирование в Microsoft .NET   Разработка параллельных приложений для ОС Windows                    259


      При постановке в очередь асинхронного вызова можно указать объ-                             gd, 1000, false
ект, который является аргументом асинхронной процедуры (при создании                           );
собственных потоков передача аргументов процедуре потока затрудни-                             Thread.Sleep( 2500 );
тельна).                                                                                       ev.Set();
      Второй способ вызова асинхронных процедур связан с использованием                        Console.ReadLine();
объектов, производных от класса System.Threading.WaitHandle (это события                   }
и мьютексы). При этом вызов асинхронной процедуры связывается с пере-                  }
водом объекта в свободное состояние. Данный метод может быть использо-               }
ван также для организации повторяющегося через определенные интервалы                Приведенный пример демонстрирует использование периодического
вызова асинхронных процедур – при регистрации делегата указывается ма-          вызова асинхронной процедуры – при регистрации делегата
ксимальный интервал ожидания, и если он исчерпывается, то вызов разме-          (RegisterWaitForSingleObject) указывается максимальное время ожидания
щается в очереди пула, даже если объект остался занятым. Если объект по-        1 секунда (1000 миллисекунд), после чего основной поток переводится в
прежнему остается занятым, то вызов процедуры будет периодически разме-         состояние «спячки» на 2.5 секунды. За это время в очередь пула поступает
щаться в очереди после исчерпания каждого интервала ожидания.                   два вызова асинхронных процедур (с признаком вызова по тайм-ауту). Че-
                                                                                рез 2.5 секунды основной поток пробуждается, переводит событие в сво-
      using System;                                                             бодное состояние, и в очередь пула поступает третий вызов. При обработ-
      using System.Threading;                                                   ке этого вызова регистрация делегата отменяется.
                                                                                     Последний способ связан с использованием методов BeginInvoke и
      namespace TestNamespace {                                                 EndInvoke делегатов. Когда определяется какой-либо делегат функции, для
        class GreetingData {                                                    него будут определены методы: BeginInvoke (содержащий все аргументы
          private string                  m_greeting;                           делегата плюс два дополнительных – AsyncCallback, который может быть
          private RegisteredWaitHandle    m_waithandle;                         вызван по завершении обработки асинхронного вызова, и AsyncState, с
          public GreetingData( string text ) { m_greeting = text; }             помощью которого можно определить состояние асинхронной процеду-
          public void Invoke() { Console.WriteLine( m_greeting ); }             ры) и EndInvoke, содержащий все выходные параметры (т.е. описанные как
          public RegisteredWaitHandle WaitHandle {                              inout или out), плюс IAsyncResult, позволяющий узнать результат выпол-
             set {                                                              нения процедуры.
               if (value==null) m_waithandle.Unregister( null );                     Таким образом, использование BeginInvoke позволяет не только по-
               m_waithandle = value;                                            ставить в очередь вызов асинхронной процедуры, но также связать с за-
             }                                                                  вершением ее обработки еще один асинхронный вызов. Метод EndInvoke
          }                                                                     служит для ожидания завершения обработки асинхронной процедуры:
        }
        class TestApp {                                                              using System;
          static void AsyncProc( Object arg, bool isTimeout ) {                      using System.Threading;
             GreetingData gd = (GreetingData)arg;
             if ( !isTimeout ) gd.WaitHandle = null;                                 namespace TestNamespace {
             gd.Invoke();                                                              public class GreetingData {
          }                                                                              private string    m_greeting;
          public static void Main() {                                                    public GreetingData( string text ) { m_greeting = text; }
             GreetingData     gd = new GreetingData(“Hello”);                            public static void Invoke( GreetingData arg ) {
             AutoResetEvent   ev = new AutoResetEvent(false);                               Console.WriteLine( arg.m_greeting );
             gd.WaitHandle=ThreadPool.RegisterWaitForSingleObject(                       }
               ev, new WaitOrTimerCallback(AsyncProc),                                 }