Использование преобразования группы методов вместо делегата в порядке, EndInvoke
все равно будет вызываться на вашем Action
. Больше ничего не поделаешь, так как это огонь и забудьте позвонить.
К сожалению, трудно прямо необоснованно доказать, что EndInvoke вызывается, поскольку Action
является делегатом, и мы не можем просто добавить точку останова в некоторый класс в BCL.
Этот код (периодически) проверять некоторые частные поле IAsyncResult, возвращенного BeginInvoke
, который, кажется, чтобы отслеживать, была ли EndInvoke
была вызвана:
public partial class MainWindow : Window
{
private Timer _timer = new Timer(TimerCallback, null, 100, 100);
private static IAsyncResult _asyncResult;
public MainWindow()
{
InitializeComponent();
}
static void LongRunTime()
{
Thread.Sleep(1000);
}
void Window_Loaded(object sender, RoutedEventArgs args)
{
Action myAction =() => LongRunTime();
_asyncResult = myAction.BeginInvoke(myAction.EndInvoke, null);
}
static void TimerCallback(object obj)
{
if (_asyncResult != null)
{
bool called = ((dynamic)_asyncResult).EndInvokeCalled;
if (called)
{
// Will hit this breakpoint after LongRuntime has completed
Debugger.Break();
_asyncResult = null;
}
}
}
}
Я проверил используя SOS, что нет утечек управляемой памяти. Я также попробовал несколько других доказательств, но они были более косвенными, чем эта, я думаю.
Некоторое интересное, которое я обнаружил в ходе моего расследования: вызов myAction.BeginInvoke
будет отображаться на профилографах с использованием приборов, но myAction.EndInvoke
нет.
Я не вижу проблем с использованием преобразования группы методов над выражением лямбда. – Thorarin
Если вы можете добавить ответ так или иначе, если эта техника не вызовет утечку памяти, тогда это будет ответом, который я ищу. Благодаря! –