Редактировать: Перенесено актуальное вопрос на верх.Как я могу избежать передачи/хранения делегата при использовании BeginInvoke и EndInvoke?
Обновление: Нашел пример Microsoft, в конце которого был добавлен еще один код.
Мои вопросы таковы:
- Безопасно позвонить множественным BeginInvoke призывает тот же экземпляр делегата, или я должен построить новый экземпляр делегата для каждого вызова метода в полете?
- Если мне нужно построить новые экземпляры для каждого, есть ли способ получить исходный делегат из значения IAsyncResult?
- Есть ли какой-нибудь другой, лучший способ добавить асинхронную поддержку в мой класс, чем использование делегатов?
Подробнее см. Далее.
Я добавляю асинхронную поддержку моему классу и думал, что сделаю это просто.
Возьмите этот класс:
public class Calculator
{
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
}
Я думал, что я мог бы просто сделать это:
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b,
AsyncCallback callback, Object obj)
{
return new AddDelegate(Add).BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
return new AddDelegate(Add).EndInvoke(ar);
}
}
Это не работает, так как эти два метода каждый построить свой собственный объект делегата и им. Проверка вызовов EndInvoke, чтобы проверить, является ли экземпляр делегата, который я вызываю, тот же, что и тот, который я изначально называл BeginInvoke.
Самый простой способ справиться с этим было бы просто сохранить ссылку на переменную, например:
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
private AddDelegate _Add;
public Calculator()
{
_Add = new AddDelegate(Add);
}
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b,
AsyncCallback callback, Object obj)
{
return _Add.BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
return _Add.EndInvoke(ar);
}
}
Обратите внимание, что я в полной мере осведомлены о проблемах с предоставлением нескольких методов экземпляра на одном классе в выполнять в то же время, по отношению к общему состоянию и т.д.
Update: Я нашел этот пример здесь Microsoft на Asynchronous Delegates Programming Sample. Он показывает, что ссылка на IAsyncResult ссылается на объект AsyncResult, а затем я могу получить исходный экземпляр делегата через свойство AsyncDelegate.
Это безопасный подход?
Другими словами, это класс класса?
public class Calculator
{
private delegate Int32 AddDelegate(Int32 a, Int32 b);
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public IAsyncResult BeginAdd(Int32 a, Int32 b, AsyncCallback callback, Object obj)
{
return new AddDelegate(Add).BeginInvoke(a, b, callback, obj);
}
public Int32 EndAdd(IAsyncResult ar)
{
AddDelegate del = (AddDelegate)((AsyncResult)ar).AsyncDelegate;
return del.EndInvoke(ar);
}
}
мне нужно возвращаемые значения, так IAsyncResult и поддержка делегатов выглядит пятно на для моих потребностей, но я Посмотрите на свой код. Обратите внимание, что два статических метода RunAsync, которые вы определили там, имеют один и тот же список параметров, поэтому они не будут компилироваться. –
Хорошо, полагаю, я обнаружил, что пропустил через AsyncResult во время написания. Так это безопасно? Там не будет ситуации с такими делегатами, где возвращенный объект * не * объект AsyncResult? (обратите внимание, что я не спрашиваю об IAsyncResult в общем случае, просто от delegate.BeginInvoke.) –
См. мой ответ для метода, который не зависит от конкретной реализации IAsyncResult – thecoop