Может использование лямбд как причина обработчиков событий утечка памяти?

Вы можете использовать следующий метод для выполнения последовательности задач и создания новой последовательности задач, которые представляют начальные задачи, но возвращаются в порядке их завершения:

public static IEnumerable<Task<T>> Order<T>(this IEnumerable<Task<T>> tasks)
{
    var taskList = tasks.ToList();

    var taskSources = new BlockingCollection<TaskCompletionSource<T>>();

    var taskSourceList = new List<TaskCompletionSource<T>>(taskList.Count);
    foreach (var task in taskList)
    {
        var newSource = new TaskCompletionSource<T>();
        taskSources.Add(newSource);
        taskSourceList.Add(newSource);

        task.ContinueWith(t =>
        {
            var source = taskSources.Take();

            if (t.IsCanceled)
                source.TrySetCanceled();
            else if (t.IsFaulted)
                source.TrySetException(t.Exception.InnerExceptions);
            else if (t.IsCompleted)
                source.TrySetResult(t.Result);
        }, CancellationToken.None, TaskContinuationOptions.PreferFairness, TaskScheduler.Default);
    }

    return taskSourceList.Select(tcs => tcs.Task);
}

Теперь, когда вы имеют возможность заказывать задачи на основе их завершения, вы можете написать код в основном так, как ваши требования диктуют:

foreach(var task in myTaskList.Order())
    if(!await task)
        cancellationTokenSource.Cancel();
20
задан Charles Menguy 25 April 2012 в 17:01
поделиться

5 ответов

Да, сохраните его к переменной и отсоедините его.

DelegateType evt = (o, e) => { firedCount++; Console.Write(firedCount); };
foo.AnEvent += evt;
foo.MethodThatFiresAnEvent();
foo.AnEvent -= evt;

И да, если Вы не делаете, Вы будете утечка память, поскольку Вы поднимете трубку новый объект делегата каждый раз. Вы также заметите это, потому что каждый раз Вы называете этот метод, он выведет к консоли растущее число строк (не только растущее число, но и для одного вызова к MethodThatFiresAnEvent он выведет любое количество объектов, однажды для каждого поднятого трубку анонимного метода).

16
ответ дан 30 November 2019 в 00:56
поделиться

Хорошо можно расширить то, что было сделано здесь для создания делегатов более в безопасности использовать (никакие утечки памяти)

3
ответ дан 30 November 2019 в 00:56
поделиться

Вы привычка просто пропускает память, Вы также назовете свою лямбду многократно. Каждый вызов 'PotentialMemoryLeaker' добавит другую копию лямбды к списку событий, и каждую копию назовут, когда 'AnEvent' будет запущен.

4
ответ дан 30 November 2019 в 00:56
поделиться

Ваш пример просто компилирует в названный компилятором частный внутренний класс (с полем firedCount и названным компилятором методом). Каждый вызов к PotentialMemoryLeaker создает новый экземпляр класса закрытия, на, который где нечто сохраняет ссылку посредством делегата в отдельном методе.

, Если Вы не ссылаетесь на целый объект, который владеет PotentialMemoryLeaker, затем это будет все собрано "мусор". Иначе можно или установить нечто , чтобы аннулировать или освободить список обработчика событий нечто путем записи этого:

foreach (var handler in AnEvent.GetInvocationList()) AnEvent -= handler;

, Конечно, Вам был бы нужен доступ к члены парламента, не занимающие официального поста MyObject класса.

2
ответ дан 30 November 2019 в 00:56
поделиться

Да таким же образом, что нормальные обработчики событий могут вызвать утечки. Поскольку лямбда на самом деле изменяется на:

someobject.SomeEvent += () => ...;
someobject.SomeEvent += delegate () {
    ...
};

// unhook
Action del = () => ...;
someobject.SomeEvent += del;
someobject.SomeEvent -= del;

Так в основном это - просто стенография для того, что мы использовали в 2,0 все эти годы.

0
ответ дан 30 November 2019 в 00:56
поделиться
Другие вопросы по тегам:

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