std :: bind эквивалент в C # или VB.NET

Я нахожусь в процессе рефакторинга «синхронного» кода (то есть использует события Windows, чтобы дождаться, пока какой-то другой поток завершит выполнение чего-либо) в «асинхронный» код (используя делегатов для реализации механизма обратного вызова).

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

В C ++ я использую std::bind обойти это. Я просто добавляю столько параметров, сколько локальных переменных, необходимых для обработчика обратного вызова, и связываю их при вызове асинхронного метода. Например, допустим, что обратный вызов асинхронного метода получает объект типа CallbackParam и вызывающая сторона использует две локальные переменные типа LocalA а также LocalB,

void AsyncClass::MethodWhichCallsAsyncMethod(){
LocalA localVarA;
LocalB localVarB;
// OnAsyncMethodDone will need localVarA and localVarB, so we bind them
AsyncMethod( std::bind( &AsyncClass::OnAsyncMethodDone, this, std::placeholders::_1, localVarA, localVarB ) );
}

void AsynClass::AsyncMethod( std::function<void(CallbackParam)> callback ){
CallbackParam result;
//Compute result...
if( callback )
callback( result );
}

void AsyncClass::OnAsyncMethodDone( CallbackParam p, LocalA a, LocalB b ){
//Do whatever needs to be done
}

Есть ли какой-то эквивалент этого в C # и VB.NET? Использование делегатов или что-то еще?

ОБНОВИТЬДля полноты картины вот эквивалент C # моего примера, основанный на ответе @ lasseespeholt:

using System;

public class AsyncClass {

public void MethodWhichCallsAsyncMethod() {
var a = new LocalA();
var b = new LocalB();
//Anonymous callback handler (equivalent to AsyncClass::OnAsyncMethodDone)
Action<CallbackParam> callback = result => {
//Do what needs to be done; result, a and b can be accessed
};
AsyncMethod( callback );
}

private void AsyncMethod( Action<CallbackParam> callback ) {
var result = new CallbackParam();
//Compute result...
if( callback != null )
callback( result );
}
}

4

Решение

ОБНОВЛЕНИЕ: Это почти наверняка не должно использоваться. Используйте ключевые слова async / await в C #

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

void MethodWhichCallsAsyncMethod()
{
int foo = 1;

AsyncCallback callback = result =>
{
Console.WriteLine(foo); // Access to foo
};

AsyncMethod(callback);
}

void AsyncMethod(AsyncCallback callback)
{
IAsyncResult result = null; // Compute result
callback(result);
}

Компилятор генерирует класс, который содержит «foo», поэтому вы ничего не сохраняете с этим подходом, но он чистый.

3

Другие решения

Других решений пока нет …