2010-02-06 3 views
31

나는 스레드 안전하다고 생각되는이 작은 메소드를 가졌습니다. 모든 것은 내가 void가 아닌 반환 값을 갖기를 원할 때까지 작동합니다. BeginInvoke가 호출 될 때 어떻게 반환 값을 얻습니까?BeginInvoke/Invoke가 C#에서 호출 될 때 반환 값을 얻는 방법

public static string readControlText(Control varControl) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new MethodInvoker(() => readControlText(varControl))); 
     } else { 
      string varText = varControl.Text; 
      return varText; 
     } 

    } 

편집 : 내가 가진 같아요 BeginInvoke 스레드 계속하기 전에 내가 GUI에서 값을 필요로하는이 경우 nessecary되지 않습니다. 그래서 Invoke를 사용하는 것이 좋습니다. 다음 예제에서 값을 반환하는 데이를 사용하는 방법에 대한 단서가 없습니다.

private delegate string ControlTextRead(Control varControl); 
    public static string readControlText(Control varControl) { 
     if (varControl.InvokeRequired) { 
      varControl.Invoke(new ControlTextRead(readControlText), new object[] {varControl}); 
     } else { 
      string varText = varControl.Text; 
      return varText; 
     } 

    } 

하지만 그 중 하나 코드를 사용하여 값을 얻을하는 방법을 잘;)

+0

"연속 통과 스타일"패턴이 필요하기 때문에 호출에서 반환 된 값으로 작업해야합니다. 'async','await' 및'Task'로 완화 될 수 있습니다. –

답변

49

함수를 반환하고 반환 값을 얻기 위해 Invoke()를 호출해야합니다. 또 다른 대의원 유형이 필요합니다. 이 작동한다고하십시오 BeginInvoke 호출에서 반환 값을 얻기 위해 사용될 수있다

public static string readControlText(Control varControl) { 
    if (varControl.InvokeRequired) { 
    return (string)varControl.Invoke(
     new Func<String>(() => readControlText(varControl)) 
    ); 
    } 
    else { 
    string varText = varControl.Text; 
    return varText; 
    } 
} 
1

당신이, 당신은 방법의 비동기 버전을 사용해서는 안하면 메소드로부터 반환 값을 원하는 경우에, 당신은 .Invoke(...)를 사용한다 . 그것은 동기식입니다. 즉, 대리인을 실행하고 완료 될 때까지 돌아 오지 않습니다. 지금 귀하의 예제에서, BeginInvoke는 귀하의 대의원을 실행하라는 요청을 보내고 곧바로 돌아옵니다. 그래서 돌아올 것이 없습니다.

+0

Invoke 또는 BeginInvoke는 값을 반환 할 수 있습니다. 내가 필요한 것은 다른 스레드에서 combobox 또는 텍스트 상자의 가치를 읽는 것입니다. – MadBoy

1

원하는 것이 무엇입니까?

+0

아닙니다. ComboBox 또는 TextBox 값을 읽고 싶어서 그 값이 다른 명령을 실행하는 것이 중요하기 때문에 BeginInvoke의 사용은 nessecary가 아닙니다. 그래서 Invoke에서 사용할 수 있습니다. 그냥 주된 목적이 다른 스레드에서 메서드를 호출하고, GUI 값을 읽고, 다시 프로그램이 나아갈 수 있도록 제게 돌아 가면 제 예제를 어떻게 사용할 수 있을지 모르겠습니다. – MadBoy

3
public static string readControlText(Control varControl) 
{ 
    if (varControl.InvokeRequired) 
    { 
     string res = ""; 
     var action = new Action<Control>(c => res = c.Text); 
     varControl.Invoke(action, varControl); 
     return res; 
    } 
    string varText = varControl.Text; 
    return varText; 
} 
+0

nobugz 솔루션과 유사하지만 그의 외모가 내게 더 깨끗해 보인다 :-) – MadBoy

+0

그래, 나는 동의한다. 내 솔루션을 게시 할 때 아직 nobugz 솔루션을 볼 수 없습니다 :) –

16

EndInvoke. 예를 들면 :

public static void Main() 
    { 
     // The asynchronous method puts the thread id here. 
     int threadId; 

     // Create an instance of the test class. 
     AsyncDemo ad = new AsyncDemo(); 

     // Create the delegate. 
     AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); 

     // Initiate the asychronous call. 
     IAsyncResult result = caller.BeginInvoke(3000, 
      out threadId, null, null); 

     Thread.Sleep(0); 
     Console.WriteLine("Main thread {0} does some work.", 
      Thread.CurrentThread.ManagedThreadId); 

     // Call EndInvoke to wait for the asynchronous call to complete, 
     // and to retrieve the results. 
     string returnValue = caller.EndInvoke(out threadId, result); 

     Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", 
      threadId, returnValue); 
    } 
} 
+0

내 경우에는 nobugz 솔루션이 완벽하고 꼭 필요한 것은 있지만 전반적인 좋은 예입니다. – MadBoy

0
delegate string StringInvoker(); 
    string GetControlText() 
    { 
     if (control.InvokeRequired) 
     { 
      string controltext = (string)control.Invoke(new StringInvoker(GetControlText)); 
      return(controltext); 
     } 
     else 
     { 
      return(control.Text); 
     } 
    } 

// 우아한 & 간단하지만이 대리자를 실행하는 다른 스레드를 기다릴 필요하다; 그러나 결과없이 진행할 수없는 경우 ...

관련 문제