ejemplo - enumeraciones c#
Cómo obtener el valor de retorno cuando BeginInvoke/Invoke se llama en C# (6)
¿Es algo como esto lo que querías?
// 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);
Tengo este pequeño método que se supone que es seguro para subprocesos. Todo funciona hasta que quiero que tenga valor de retorno en lugar de vacío. ¿Cómo obtengo el valor de retorno cuando se llama a BeginInvoke?
public static string readControlText(Control varControl) {
if (varControl.InvokeRequired) {
varControl.BeginInvoke(new MethodInvoker(() => readControlText(varControl)));
} else {
string varText = varControl.Text;
return varText;
}
}
Editar: supongo que tener BeginInvoke no es nessecary en este caso ya que necesito valor de GUI antes de que el hilo pueda continuar. Entonces, usar Invoke también es bueno. Simplemente no tengo idea de cómo usarlo en el siguiente ejemplo para devolver el valor.
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;
}
}
Pero no estoy seguro de cómo obtener valor utilizando ese código;)
Si desea un valor de retorno de su método, no debe utilizar una versión asincrónica del método, debe usar .Invoke(...)
. Que es sincrónico, es decir ejecutará su delegado y no volverá hasta que esté completo. En su ejemplo como está ahora, BeginInvoke enviará la solicitud para ejecutar a su delegado, y regresará de inmediato. Entonces no hay nada a lo que regresar.
Tienes que invocar () para que puedas esperar a que la función regrese y obtener su valor de retorno. También necesitarás otro tipo de delegado. Esto debería funcionar:
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;
}
}
EndInvoke
se puede usar para obtener un valor de retorno de una llamada a BeginInvoke
. Por ejemplo:
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);
}
}
delegate string StringInvoker();
string GetControlText()
{
if (control.InvokeRequired)
{
string controltext = (string)control.Invoke(new StringInvoker(GetControlText));
return(controltext);
}
else
{
return(control.Text);
}
}
// simple y elegante pero es necesario esperar a que otro subproceso ejecute delegar; sin embargo, si no puede continuar sin los resultados ...
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;
}