2010-02-06 22 views
31

我有這個應該是線程安全的小方法。一切工作,直到我想它有返回值而不是無效。如何在調用BeginInvoke時獲取返回值?如何在C#中調用BeginInvoke/Invoke時返回值

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'來緩解。 – 2016-09-23 01:44:15

回答

49

您必須調用(),以便您可以等待函數返回並獲取其返回值。你還需要另一個委託類型。這應該工作:

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。我所需要的是從其他線程讀取組合框或文本框的值。 – MadBoy 2010-02-06 17:54:14

1

是這樣的東西你想要什麼?

// begin execution asynchronously 
IAsyncResult result = myObject.BeginInvoke("data.dat", null, null); 

// wait for it to complete 
while (result.IsCompleted == false) { 
    // do some work 
    Thread.Sleep(10); 
    } 

// get the return value 
int returnValue = myObject.EndInvoke(result); 
+0

不完全。我猜BeginInvoke的使用不是nessecary,因爲我只是想讀取ComboBox或TextBox的值,並且該值對於執行其他命令很重要。所以我可以在Invoke中使用它。只是不知道我怎麼可以在我的情況下使用你的例子,其主要目的是從另一個線程調用方法,讀取gui值並返回給我,所以程序可以走得更遠。 – MadBoy 2010-02-06 17:57:23

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 2010-02-06 18:23:04

+0

是的,我同意。當我發佈我的解決方案時,我沒有看到nobugz解決方案:) – 2010-02-06 18:25:51

16

EndInvoke可用於獲取從BeginInvoke調用的返回值。例如:

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 2010-02-06 18:30:07

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

//簡單&優雅,但它是需要等待另一個線程來執行代表;然而,如果你不能沒有結果繼續......