Универсальное асинхронное присвоение

#c# #winforms #asynchronous #lambda

#c# #winforms #асинхронный #лямбда

Вопрос:

Я пытаюсь создать метод, который асинхронно присваивается в программе Winforms с использованием BackgroundWorker .

 void Assign<T>(Func<object> method, ref T obj)
{
    var bw = new BackgroundWorker();
    bw.DoWork  = 
        (object sender, DoWorkEventArgs e) => 
            e.Result = ((Func<object>)(e.Argument))();
    bw.RunWorkerCompleted  = 
        (object sender, RunWorkerCompletedEventArgs e) =>
            obj = (T)e.Resu< // Error here
    bw.RunWorkerAsync(method);
}

Assign(slowMethodReturnsFloat, ref aFloatVariable);
Assign(slowMethodReturnsDataSet, ref aDataSetVar);
  

Однако я получил ошибку:

«Невозможно использовать параметр ref или out внутри лямбда-выражения»

Есть ли другой способ его реализации? Какой-либо подход не используется BackgroundWorker ?

Комментарии:

1. Почему бы вам просто не вернуться T ? (неважно, вы пытаетесь сохранить рабочий процесс с помощью BGworker, а не сделать асинхронным).

2. Это bw.DoWork = (object sender, DoWorkEventArgs e) => ... прямой путь к утечке памяти

3. @T.S. Можете ли вы дать некоторые подробности об DoWork утечке памяти и?

4. Вы подписываетесь на событие и не отказываетесь от подписки. Это одна из тех вещей, которые часто забывают программисты. Вы должны сделать var handler = (object sender, DoWorkEventArgs e) => ...; bw.DoWork = handler; , а затем bw.DoWork -= handler; увидеть ловушку # 5 visualstudiomagazine.com/articles/2010/08/31 /…

5. @T.S. Спасибо. Какое лучшее место для отмены подписки DoWork и RunWorkCompleted ? Внутренняя часть кода подписана RunWorkCompleted ? Или закрыть форму? Интересно, что пример статьи MSDN даже не отменяет подписку на события msdn.microsoft.com/en-us/library/cc221403 (v= против 95).aspx .

Ответ №1:

Рассмотрите возможность передачи лямбда-выражения вместо в ref качестве второго аргумента:

 void Assign<T>(Func<object> method, Action<T> objSetter)
{
    var bw = new BackgroundWorker();
    bw.DoWork  = 
        (object sender, DoWorkEventArgs e) => 
            e.Result = ((Func<object>)(e.Argument))();
    bw.RunWorkerCompleted  = 
        (object sender, RunWorkerCompletedEventArgs e) =>
            objSetter((T)e.Result);
    bw.RunWorkerAsync(method);
}

Assign(slowMethodReturnsFloat, ret => aFloatVariable = ret);
Assign(slowMethodReturnsDataSet, ret => aDataSetVar = ret);
  

Ответ №2:

Я не уверен, что T это такое, но другим вариантом может быть передача обратного вызова:

 void Assign<T>(Func<object> method, Action<T> callBack);

void callBack(T result)