Один способ исследовать это состоит в том, чтобы посмотреть на код в WinDbg. Так, учитывая код ниже, давайте посмотрим, как это появляется на "куче".
var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
первое, что нужно сделать состоит в том, чтобы определить местоположение экземпляра. Поскольку я сделал это локальным в Main()
, легко найти адрес экземпляра.
От адреса мы можем вывести фактический экземпляр, который дает нам:
0:000> !do 0x0141ffc0
Name: System.Int32[]
MethodTable: 01309584
EEClass: 01309510
Size: 52(0x34) bytes
Array: Rank 1, Number of elements 10, Type Int32
Element Type: System.Int32
Fields:
None
Это говорит нам, что это - наш массив Int32 с 10 элементами и общим размером 52 байтов.
Позволяют нам вывести память, где экземпляр расположен.
0:000> d 0x0141ffc0
0141ffc0 [84 95 30 01 0a 00 00 00-00 00 00 00 01 00 00 00 ..0.............
0141ffd0 02 00 00 00 03 00 00 00-04 00 00 00 05 00 00 00 ................
0141ffe0 06 00 00 00 07 00 00 00-08 00 00 00 09 00 00 00 ................
0141fff0 00 00 00 00]a0 20 40 03-00 00 00 00 00 00 00 00 ..... @.........
01420000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01420010 10 6d 99 00 00 00 00 00-00 00 01 40 50 f7 3d 03 .m.........@P.=.
01420020 03 00 00 00 08 00 00 00-00 01 00 00 00 00 00 00 ................
01420030 1c 24 40 03 00 00 00 00-00 00 00 00 00 00 00 00 .$@.............
я вставил скобки для 52 байтов.
Редактирование: Забыл длину в первой регистрации.
список является немного неправильным, потому что, поскольку romkyns указывает, что экземпляр на самом деле начинается в адресе - 4, и первым полем является Syncblock.
Вы можете создать подкласс ThreadPoolExecutor и добавить перехватчики с beforeExecute и afterExecute для отслеживания выполнения задачи, как вам нравится, включая базовую математику для подсчета текущих выполняемых задач. Также есть прямой доступ к очереди с помощью getQueue ().
Между ними вы можете легко реализовать запрашиваемое вами отслеживание. Мне любопытно, каков ваш вариант использования ... что вы будете делать с пулом, когда он пуст?
I am wondering if this would work in a real world environment. It involves subclassing ThreadPoolExecutor
and passing it an IdleListener
:
@Override
protected void beforeExecute(Thread t, Runnable r)
{
super.beforeExecute(t, r);
listener.working();
}
@Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
long activeCount = getTaskCount() - getCompletedTaskCount();
if (activeCount == 1) // yes, one
{
listener.idle();
}
}
The interface:
interface IdleListener
{
void working();
void idle();
}