After asking this question, I am wondering if it is possible to wait for an event to be fired, and then get the event data and return part of it. Sort of like this:
private event MyEventHandler event; public string ReadLine(){ return event.waitForValue().Message; } ... event("My String"); ...elsewhere... var resp = ReadLine();
Please make sure whatever solution you provide returns the value directly rather than getting it from something else. I'm asking if the method above is available in some way. I know about Auto/ManuelResetEvent, but I don't know that they return the value directly like I did above.
Update: I declared an event using MyEventHandler
(which contains a Message
field). I have a method in another thread called ReadLine
waiting for the event to fire. When the event fires the WaitForValue method (part of the event handling scene) returns the event args, which contains the message. The message is then returned by ReadLine to whatever had called it.
The accepted answer to that question I asked was what I did, but it just doesn't feel quite right. It almost feels like something could happen to the data between the ManuelResetEvent firing and the program retrieving the data and returning it.
Update: The main problem with the Auto/ManualResetEvent
is that it is too vulnerable. A thread could wait for the event, and then not give enough time for anyone else to get it before changing it to something else. Is there a way to use locks or something else? Maybe using get and set statements.
If the current method is async then you can use TaskCompletionSource. Create a field that the event handler and the current method can access.
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); }
This example uses a form that has a textblock named WelcomeTitle and two buttons. When the first button is clicked it starts the click event but stops at the await line. When the second button is clicked the task is completed and the WelcomeTitle text is updated. If you want to timeout as well then change
await tcs.Task;
to
await Task.WhenAny(tcs.Task, Task.Delay(25000)); if (tcs.Task.IsCompleted) WelcomeTitle.Text = "Task Completed"; else WelcomeTitle.Text = "Task Timed Out";
You can use ManualResetEvent. Reset the event before you fire secondary thread and then use the WaitOne() method to block the current thread. You can then have secondary thread set the ManualResetEvent which would cause the main thread to continue. Something like this:
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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With