WaitHandle.WaitAnyを呼び出すと、指定されたWaitHandle[]のコピーが割り当てられることに気づきました。以下のリンクまたはリフレクターを使用して見ることができるように:
関連するコードは次のとおりです。
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
if (waitHandles==null)
{
throw new ArgumentNullException("waitHandles");
}
if (MAX_WAITHANDLES < waitHandles.Length)
{
throw new NotSupportedException(Environment.GetResourceString("NotSupported_MaxWaitHandles"));
}
if (-1 > millisecondsTimeout)
{
throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
}
WaitHandle[] internalWaitHandles = new WaitHandle[waitHandles.Length];
for (int i = 0; i < waitHandles.Length; i ++)
{
WaitHandle waitHandle = waitHandles[i];
if (waitHandle == null)
throw new ArgumentNullException(Environment.GetResourceString("ArgumentNull_ArrayElement"));
if (RemotingServices.IsTransparentProxy(waitHandle))
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy"));
internalWaitHandles[i] = waitHandle;
}
#if _DEBUG
// make sure we do not use waitHandles any more.
waitHandles = null;
#endif
int ret = WaitMultiple(internalWaitHandles, millisecondsTimeout, exitContext, false /* waitany*/ );
for (int i = 0; i < internalWaitHandles.Length; i ++)
{
GC.KeepAlive (internalWaitHandles[i]);
}
if ((WAIT_ABANDONED <= ret) && (WAIT_ABANDONED+internalWaitHandles.Length > ret))
{
int mutexIndex = ret -WAIT_ABANDONED;
if(0 <= mutexIndex && mutexIndex < internalWaitHandles.Length)
{
throw new AbandonedMutexException(mutexIndex,internalWaitHandles[mutexIndex]);
}
else
{
throw new AbandonedMutexException();
}
}
else
return ret;
}
今私の質問はなぜですか?これを回避することはできますか(つまり、WaitHandle.WaitAnyの独自のコピーを作成します)?そして、おそらくなぜですか?
これは、私のシステムに多くの不要なメモリ割り当てがあることを意味します。低レベルの方法のため、これを複数のWaitHandlesで使用します。
トピックにとどまり、タスク並列ライブラリまたは同様のものへの参照を控えてください;)ここでは、GC圧力が重要な高性能シナリオについて話しています。