Invoke와 DynamicInvoke의 차이점


128

델리게이트에서 Invoke와 DynamicInvoke의 차이점은 무엇입니까? 이 두 방법의 차이점을 설명하는 코드 예제를 알려주십시오.

답변:


206

델리게이트 인스턴스가있는 경우 정확한 유형을 알거나 해당 유형이임을 알 수 있습니다 Delegate. 정확한 유형을 알고 있다면을 사용할 수 있습니다 Invoke. 매우 빠릅니다 . 모든 것이 이미 사전 검증되었습니다. 예를 들면 다음과 같습니다.

Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);

하나! 당신이 그것을 알고 있다면 Delegate, 매개 변수 등을 수동으로 해결해야합니다-이것은 unboxing을 포함 할 수 있습니다. 예를 들면 다음과 같습니다.

Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);

참고 사항 이 포함되어 args있음을 분명히하기 위해 긴 손을 썼습니다 object[]. 여기에 많은 추가 비용이 있습니다 :

  • 배열
  • 전달 된 인수의 유효성을 검사하는 것이 실제에 "적합한" MethodInfo
  • 필요에 따라 개봉 등
  • 반사 호출
  • 호출자는 반환 값을 처리하기 위해 무언가를해야합니다.

기본적으로 가능 DynamicInvoke하면 항상 피하십시오 . Invoke모든 것이 a Delegate및 a가 아닌 한 항상 선호 object[]됩니다.

성능 비교를 위해 디버거 외부의 릴리스 모드 (콘솔 exe)에서 다음이 인쇄됩니다.

Invoke: 19ms
DynamicInvoke: 3813ms

암호:

Func<int,int> twice = x => x * 2;
const int LOOP = 5000000; // 5M
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
    twice.Invoke(3);
}
watch.Stop();
Console.WriteLine("Invoke: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
    twice.DynamicInvoke(3);
}
watch.Stop();
Console.WriteLine("DynamicInvoke: {0}ms", watch.ElapsedMilliseconds);

3
사용의 경우 DynamicInvoke 컴파일러가 델리게이트 호출을 처리하기 위해 더 많은 IL 코드를 생성한다는 의미입니까?
testCoder

2
@testCoder 아니요, 리플렉션을 사용합니다
Marc Gravell

@MarcGravell 이벤트를 발생시키는 메소드에서 이것을 시도하면 첫 번째 메소드 호출은 약 0,7766ms가 걸리고 두 번째는 0,0568ms가 걸립니다. 첫 번째가 Invoke 인 경우 DynamicInvoke보다 시간이 오래 걸리거나 그 반대입니다. 1 루프로 예제를 시도하고 ms을 보았습니다 Invoke: 0,0478ms, DynamicInvoke: 0,053ms. 왜 둘 이상의 통화를 비교합니까? 왜 첫 번째 함수가 두 번째 함수 호출보다 시간이 더 걸리나요?
uzay95

4
@ uzay95 메소드를 처음 호출하면 CLR이 JIT 컴파일을 수행합니다. 이는 프로세스가 시작된 후 처음 호출 될 때 모든 메소드에 적용됩니다. 이런 종류의 시나리오에서는 다음 세 가지 중 하나를 수행 할 수 있습니다. 메소드를 한 번 호출했거나 (3) ngen.exe (오버 킬)를 사용하십시오. 이 게시물은 충분히 설명합니다 ... stackoverflow.com/questions/4446203/…
Quanta

@ marc-gravell 메소드 서명 은 args 매개 변수 의 params 키워드를 명시하기 때문에 DynamicInvoke에 전달할 배열을 만들 필요가 없습니다 .
zodo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.