visual - Cómo bloquear hasta que se active un evento en c#




visual studio events c# (3)

Puede usar ManualResetEvent. Restablezca el evento antes de disparar el hilo secundario y luego use el método WaitOne () para bloquear el hilo actual. A continuación, puede configurar el hilo secundario para configurar el evento ManualResetEvent, lo que provocaría que el hilo principal continuara. Algo como esto:

ManualResetEvent oSignalEvent = new ManualResetEvent(false);

void SecondThread(){
    //DoStuff
    oSignalEvent.Set();
}

void Main(){
    //DoStuff
    //Call second thread
    System.Threading.Thread oSecondThread = new System.Threading.Thread(SecondThread);
    oSecondThread.Start();

    oSignalEvent.WaitOne(); //This thread will block here until the reset event is sent.
    oSignalEvent.Reset();
    //Do more stuff
}

Después de hacer esta pregunta , me pregunto si es posible esperar a que se dispare un evento, y luego obtener los datos del evento y devolver parte del mismo. Más o menos así:

private event MyEventHandler event;
public string ReadLine(){ return event.waitForValue().Message; }
...
event("My String");
...elsewhere...
var resp = ReadLine();

Asegúrese de que la solución que proporcione devuelva el valor directamente en lugar de obtenerlo de otra forma. Pregunto si el método anterior está disponible de alguna manera. Sé de Auto / ManuelResetEvent, pero no sé si devuelven el valor directamente como lo hice anteriormente.

Actualización: He declarado un evento usando MyEventHandler (que contiene un campo de Message ). Tengo un método en otro hilo llamado ReadLine esperando que el evento se dispare. Cuando el evento activa el método WaitForValue (parte de la escena de manejo de eventos) devuelve los eventos args, que contienen el mensaje. A continuación, ReadLine devuelve el mensaje a lo que lo llamó.

La respuesta aceptada a esa pregunta que hice fue lo que hice, pero simplemente no me siento bien. Casi parece que algo podría pasarle a los datos entre la activación ManuelResetEvent y el programa que recupera los datos y los devuelve.

Actualización: el principal problema con el Auto/ManualResetEvent es que es demasiado vulnerable. Un hilo podría esperar el evento y luego no dar tiempo suficiente para que nadie lo obtenga antes de cambiarlo a otra cosa. ¿Hay alguna manera de usar bloqueos o algo más? Tal vez usando declaraciones get y set.


Si el método actual es asíncrono, puede usar TaskCompletionSource. Cree un campo al que puedan acceder el controlador de eventos y el método actual.

    TaskCompletionSource<bool> tcs = null;

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        tcs = new TaskCompletionSource<bool>();
        await tcs.Task;
        WelcomeTitle.Text = "Finished work";
    }

    private void Button_Click2(object sender, RoutedEventArgs e)
    {
        tcs?.TrySetResult(true);
    }

Este ejemplo utiliza un formulario que tiene un bloque de texto llamado WelcomeTitle y dos botones. Cuando se hace clic en el primer botón, se inicia el evento de clic pero se detiene en la línea de espera. Cuando se hace clic en el segundo botón, la tarea se completa y el texto de WelcomeTitle se actualiza. Si también desea tiempo de espera, cambie

await tcs.Task;

a

await Task.WhenAny(tcs.Task, Task.Delay(25000));
if (tcs.Task.IsCompleted)
    WelcomeTitle.Text = "Task Completed";
else
    WelcomeTitle.Text = "Task Timed Out";

Un tipo muy fácil de evento que puede esperar es el ManualResetEvent , y aún mejor, el ManualResetEventSlim .

Tienen un método WaitOne() que hace exactamente eso. Puedes esperar por siempre, o establecer un tiempo de espera, o un "token de cancelación", que es una forma de que decidas dejar de esperar el evento (si deseas cancelar tu trabajo o se te pide que salgas).

Los disparas llamando a Set() .

Here está el documento.





events