2009-11-26 8 views
4

이 작업을 시도하고 있지만 작동하지 않습니다. 몇 가지 제안?C# lambda ref out

int test_i = 0; 
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(test_i); 
test_i <- still is 0 and not 3!!! 

public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(int i) 
{ 
    DisableUi(); 
    m_commandExecutor.ExecuteWithContinuation(
       () => 
        { 
         // this is the long-running bit 
         ConnectToServer(); 
         i = 3; <-------------------------- 
         // This is the continuation that will be run 
         // on the UI thread 
         return() => 
            { 
             EnableUi(); 
            }; 
        }); 
} 

왜 내가 test_i를 3으로 설정할 수 없습니까? 나는 또한 심판을 밖으로 시도했지만 작동하지 않습니다.

문제를 해결하려면 어떻게해야합니까?

편집

이 시도하지만,이 방법은 데이터 세트의 ouside 여전히 비어했습니다.

public static void Select(DataGridView dataGridView, ref DataSet dataSet, params object[] parameters) 
    { 
    var _dataSet = dataSet; 
    AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current); 
    commandExecutor.ExecuteWithContinuation(
    () => 
    { 
     // this is the long-running bit 
     _dataSet = getDataFromDb(parameters); 

     // This is the continuation that will be run on the UI thread 
     return() => 
     { 
      dataGridView.DataSource = _dataSet.Tables[0].DefaultView; 
     }; 
    }); 
    dataSet = _dataSet; 
    } 
+0

답을 업데이트했습니다. 희망이 도움이 : O) –

답변

8

, 당신은 람다 내부를 사용할 수 없습니다 : 당신은 적합하지 않을 수 있습니다 대리인의 서명과 대리자를받는 방법의 구현을 변경해야 표현. 업데이트 된 대답에 대응

private static void Main(string[] args) 
{ 
    int i = 0; 
    DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref i); 
    Console.WriteLine(i); 
} 


public static void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref int i) 
{ 
    int temp = i; 
    Thread t = new Thread(() => 
    { 
     temp = 3; // assign the captured, local variable  
    }); 
    t.Start(); 
    t.Join(); 

    i = temp; // assign the ref parameter 
} 

업데이트
: 문제가 _dataSet 내부입니다 가능 (다소 단순화 된 예) 경우, 람다 내부의 지역 변수를 사용하여 시도하고 외부 ref 변수에 할당 람다 식은 람다 식 외부의 dataSet과 같은 변수가 아닙니다. 위의 코드에서

public static void Select(DataGridView dataGridView, 
          DataSetContainer dataSetContainer, 
          params object[] parameters) 
{ 
    AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current); 
    commandExecutor.ExecuteWithContinuation(
    () => 
    { 
     // this is the long-running bit 
     dataSetContainer.DataSet = getDataFromDb(parameters); 

     // This is the continuation that will be run on the UI thread 
     return() => 
     { 
      dataGridView.DataSource = _dataSet.Tables[0].DefaultView; 
     }; 
    }); 

} 

}

:

class DataSetContainer 
{ 
    public DataSet DataSet { get; set; } 
} 

이제 우리는 우리가 안전하게 람다 식 내에서 수정할 수있는 속성을 참조 형식을 가지고 : 당신이 할 수있는 것은 다음과 같다 람다 식은 Select 메서드에 전달 된 DataSetContainer 인스턴스의 DataSet 속성을 업데이트합니다. 전달 된 인수 자체는 수정하지 않고 해당 인스턴스의 멤버 만 수정하므로 ref 키워드가 필요하지 않으며 폐쇄 문제도 해결됩니다. 나는 내 머리에 전환 할 때


그리고 업데이트 2는 지금, 나는 Select 방법은 비동기 호출을 실현. 마지막 줄은 메서드 인 코드가 보이기 때문에 _dataSet이 할당되기 훨씬 전에 실행될 것이므로 결과적으로 null이됩니다. 이 문제를 해결하기 위해 할당이 완료된시기를 알기 위해 일종의 신호 메커니즘 (예 : ManualResetEvent 또는 AutoResetEvent)을 사용하려고합니다.

+0

그것은 내 예제에서처럼 사용할 수 있습니까?하지만 int가 아닌 dataSet? – Jooj

+0

@Jooj : 참조 유형을 전달하면 람다 식 내부의 멤버 속성/필드를 수정할 수 있어야합니다. –

+0

제 마지막 게시물을보세요. – Jooj

7

람다 식에서 i 변수에있어서의 파라미터 i을 말한다. 이 문제를 해결하기 위해 전역 변수 (더티 솔루션)를 참조하도록 만들 수 있습니다.

그런데 you can't capture ref and out variables in lambdas하지만 매개 변수로 사용할 수 있습니다. ref 키워드를 사용하여 변수를 전달할 때

(out int i) => { i = 10; }