Почему асинхронный метод делегата требует вызова EndInvoke?

Обычно, VM сделал бы сборку "мусора" автоматически прежде, чем бросить OutOfMemoryException, так добавление, что явный вызов не должен помогать, кроме которого это, возможно, перемещает хит производительности в более ранний момент вовремя.

Однако я думаю, что встретился со случаем, где это могло бы быть релевантно. Я не уверен, хотя, поскольку я должен все же протестировать, имеет ли это какой-либо эффект:

, Когда Вы карта распределения памяти файл, я верю карте () вызов бросает IOException, когда достаточно большой блок памяти не доступен. Сборка "мусора" незадолго до карты () файл мог бы помочь предотвратить это, я думаю. Что Вы думаете?

10
задан Rashmi Pandit 11 November 2009 в 08:54
поделиться

2 ответа

Причина, по которой вам нужно вызвать EndInvoke , - это избежать утечки памяти; .Net будет хранить информацию о результате (или исключении) функции до тех пор, пока вы не вызовете EndInvoke .

Вы можете вызвать EndInvoke в обработчике завершения, который вы передаете BeginInvoke и сохранить асинхронный характер.

РЕДАКТИРОВАТЬ :

Например:

class Program {
    private delegate void GenerateXmlDelegate();

    static void Main(string[] args) {
        GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
        IAsyncResult result = worker.BeginInvoke(delegate {
            try {
                worker.EndInvoke();
            } catch(...) { ... }
        }, null);
    }

    private static void GenerateMainXml() {
        Thread.Sleep(10000);
        Console.WriteLine("GenerateMainXml Called by delegate");
    }
}

Если вы хотите запустить асинхронный вызов и забыть о нем, вы можете использовать ThreadPool , например:

ThreadPool.QueueUserWorkItem(delegate { GenerateMainXml(); });
16
ответ дан 3 December 2019 в 17:59
поделиться

Как сказал SLaks, EndInvoke обеспечивает защиту от утечек памяти.

BeginInvoke по-прежнему асинхронный; рассмотрите следующий код:

static void Main() {
    Func<double> slowCalculator = new Func<double>(PerformSlowCalculation);
    IAsyncResult slowCalculation = slowCalculator.BeginInvoke(null, null);

    // lots of stuff to do while slowCalculator is doing its thing

    Console.WriteLine("Result is {0}", slowCalculator.EndInvoke(slowCalculation));
}

static double PerformSlowCalculation() {
    double result;

    // lots and lots of code

    return result;
}

Если бы этот код был написан без вызовов BeginInvoke / EndInvoke , PerformSlowCalculation должен был бы завершиться до Main мог бы делать остальную часть своего «множества вещей»; таким образом, оба события могут происходить одновременно.

Теперь, в вашем примере с использованием GenerateXmlDelegate , вам по-прежнему требуется EndInvoke , даже если вы ничего не возвращаете. Это можно сделать следующим образом:

static void Main(string[] args) {
    GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
    IAsyncResult result = worker.BeginInvoke(GenerateXmlComplete, null);
}

private static void GenerateXmlComplete(IAsyncResult result) {
    AsyncResult realResult = result as AsyncResult;
    GenerateXmlDelegate worker = result.AsyncDelegate as GenerateXmlDelegate;
    worker.EndInvoke();
}
6
ответ дан 3 December 2019 в 17:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: