Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


Вызов метода при освобождении одного объекта ядра




Исследуя производительность, специалисты Microsoft обнаружили, что во многих приложениях создают потоки, которые просто ожидают освобождения одного объекта ядра. При освобождении объекта поток направляет определенное уведомление другому потоку, после чего опять ожидает освобождения объекта. Некоторые разработчики даже пишут код, в котором несколько потоков ожидает освобождения объекта. Это очень нерациональная трата системных ресурсов. Так что, если у вас есть потоки, ожидающие освобождения одного объекта ядра, и в этот раз лучшим решением для повышения производительности приложения будет использование пула потоков.

Чтобы поток из пула потоков вызывал нужный метод обратного вызова при освобождении объекта ядра, нужно вызвать статический метод RegisterWaitForSingleObject класса System.Threading.ThreadPool. Есть несколько перегруженных версий этого метода, но все они очень похожи. Вот прототип одной из наиболее часто используемых перегруженных версий:

 

public static RegisterWaitHandle RegisterWaitForSingleObject(

WaitHandle waitObject,

WaitOrTimerCallback callback,

Object state,

Int32 millisecondsTimeoutlnterval,

Boolean executeOnlyOnce

);

 

При вызове этого метода аргумент waitObject указывает объект ядра, освобождения которого должен ожидать пул потоков. Поскольку этот параметр унаследован от абстрактного класса WaitHandle, можно указать любой производный от него класс. В частности, можно передать ссылку на объект Semaphore, Mutex, AutoResetEvent или ManualResetEvent. Второй параметр, callback, указывает метод, который поток из пула потоков должен вызывать. Вызываемый метод должен соответствовать делегату System.Threading.WaitOrTimerCallback, который определяется следующим образом:

 

public delegate void WaitOrTimerCallback(Object state, Boolean timedOut);

 

Третий параметр метода RegisterWaitForSingleObject, state, позволяет указать некоторые данные состояния, которые нужно передать в метод обратного вызова, когда поток из пула потоков вызывает его. Если данных нет, передайте null. Четвертый параметр, millisecondsTimeoutlnterval, указывает пулу, как долго он должен ожидать освобождения объекта ядра. Чтобы задать неограниченное время ожидания, обычно передают Timeout Infinite или -1. Если последний параметр, executeOnlyOnce, равен true, пул потоков выполнит метод обратного вызова только раз.

Если же executeOnlyOnce равен false, поток из пула потоков будет выполнять метод обратного вызова при каждом освобождении объекта ядра. Это исключительно удобно при ожидании освобождения объекта AutoResetEvent.

Методу обратного вызова передаются данные состояния и логическое значение timedOut. Если timedOut равен false, метод знает, что он вызван по причине освобождения объекта ядра. Если же значение timedOut равно true, метод знает, что он вызывается потому, что объект ядра не освободился за означенное время. Метод обратного вызова может выполнять любые операции, причем выбор операции может зависеть от значения, полученного в аргументе timedOut.

Метод RegisterWaitForSingleObject возвращает ссылку на объект RegisteredWaitHandle. Последний определяет объект ядра, освобождения которого ожидает пул потоков. Если по какой-то причине приложение должно сообщить пулу потоков, что нужно прекратить наблюдение за ожидаемым описателем, вызывают метод Unregister класса RegisteredWaitHandle:

 

public Boolean Unregister(WaitHandle waitObject);

 

Значение параметра waitObject указывает, как нужно вернуть уведомление о выполнении всех рабочих элементов в очереди зарегистрированного объекта ожидания. Если уведомление не требуется, передайте null. Если надо передать корректную ссылку на объект, производный от класса WaitHandle, пул потоков сообщит объекту о выполнении всех рабочих элементов.

Приведенный ниже пример кода показывает, как поток из пула потоков вызывает метод каждый раз, когда освобождается объект AutoResetEvent:

 

using System;

using System.Threading;

 

public static class Program

{

public static void Main()

{

// Создание объекта AutoResetEvent (изначально не освобожденного).

AutoResetEvent are = new AutoResetEvent(false);

// Сообщаем пулу потоков, что нужно ожидать AutoResetEvent.

RegisteredWaitHandle rwh = ThreadPool.RegisterWaitForSingleObject(

are, // Ожидать этот объект AutoResetEvent.

EventOperation, // Выполнить обратный вызов этого метода.

null, // Передать null в качестве параметра EventOperation.

5000, // Ждать освобождения 5 секунд.

false); // Вызывать EventOperation при каждом освобождении.

 

// Запуск цикла.

Char operation;

do

{

Console.WriteLine("S=Signal, Q=Quit?");

operation = Char.ToUpper(Console.ReadKey(true).KeyChar);

if (operation == 'S')

{

// Пользователь хочет освободить событие; устанавливаем событие.

are.Set();

}

}

while (operation != 'Q');

// Сообщаем пулу потоков, что нужно прекратить ожидание события.

rwh.Unregister(null);

 

}

// Этот метод вызывается при каждом освобождении события или

// через 5 секунд после последнего освобождения/тайм-аута,

private static void EventOperation(Object state, Boolean timedOut)

{

if (timedOut)

{

Console.WriteLine("Timedout while waiting for the AutoResetEvent.");

}

else

{

Console.WriteLine("The AutoResetEvent became signaled.");

}

}

}

 

 


 


Поделиться:

Дата добавления: 2015-04-21; просмотров: 94; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.006 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты