2013-04-05 2 views
4

Я занимаюсь рефакторингом «синхронного» кода (т. Е. Использует события Windows, чтобы ждать, пока какой-либо другой поток не закончит что-то делать), в «асинхронный» код (используя делегаты для реализации механизм обратного вызова).std :: bind эквивалент в C# или VB.NET

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

В C++ я использую std::bind, чтобы обойти это. Я просто добавляю столько параметров, сколько локальных переменных, необходимых для обработчика обратного вызова, и связываю их, когда я вызываю метод async. Например, предположим, что обратный вызов асинхронного метода получает объект типа 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? Использование делегатов или что-то еще?

UPDATE: саке Для полноты, здесь 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); 
     } 
} 

ответ

3

UPDATE: Это должно почти наверняка не будет использоваться. Используйте асинхр/ждут ключевых слов в 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», так что вы ничего с этим подходом не спасти, но чисто.

+0

Выглядит хорошо; Я не хотел добавлять состояние в свой класс, но если компилятор делает это, я не против: P Это можно сделать и на VB.NET? (мы говорим .NET 4.0) –

+1

@dario_ramos Я сам не использую VB.Net, но да. C# и VB.Net разделяют большинство функций. Эта страница должна помочь вам использовать lambdas в VB.Net: http://msdn.microsoft.com/en-us/library/bb531253.aspx –

Смежные вопросы