Вам необязательно оставлять свои собственные ссылки на делегата при выполнении нормального делегат BeginInvoke
; вы можете наложить IAsyncResult
на номер AsyncResult
и получить делегат от объекта AsyncDelegate
. И прежде чем кто-нибудь скажет: «Это грязный хак», it's documented as being valid at MSDN.
Класс AsyncResult используется в сочетании с асинхронными вызовами метода, выполненными с использованием делегатов. IAsyncResult, возвращенный из метода BeginInvoke делегата, может быть перенесен в AsyncResult. AsyncResult имеет свойство AsyncDelegate, которое содержит объект делегирования, на который был вызван асинхронный вызов.
Таким образом, вы могли бы написать:
new GenericDelegate(DoSomething).BeginInvoke(DoSomethingComplete);
void DoSomethingComplete(IAsyncResult ar)
{
((GenericDelegate)((AsyncResult)ar).AsyncDelegate)).EndInvoke();
}
Обратите внимание, что вы все еще должны знать типа оригинального делегата (или, по крайней мере, я не нашел способ обойти это ограничение; то опять я не пробовал).
Под «нормальным» здесь я имею в виду BeginInvoke
на экземпляр делегата, используя метод сгенерированного компилятором. Эта технология кастинга до AsyncResult
не гарантируется при использовании заранее определенных методов, то есть при использовании класса, который объявляет свои собственные методы BeginX/EndX
. Это связано с тем, что класс может делать что-то более умное внутри, например, блокировать порты ввода IO и, следовательно, использовать другой тип IAsyncResult
. Тем не менее, в сценарии, как положено, он будет работать нормально.
Упрощенный захват «d»: d.BeginInvoke (r => {d.EndInvoke (r); ...}, null); [согласно сообщению в блоге, указанному выше]. –