-3

I have an old winform application where a winform is showed with form.ShowDialog() command. However, this approach is non-user friendly as it blocks the main UI until user closes the form. I have tried to changed the code to form.Show which unfreezes the main UI however the code keeps getting excecuted without waiting for the form to close and get the received data. Any Idea on how to implement this?

MyObject OnButtonClick(){
     var form = new MyForm();
     form.Show(); <-- await till it is closed
     MyObject results = form.MyCustomResults;
     return results;
}
Jim
  • 2,760
  • 8
  • 42
  • 66
  • @OlivierRogier He doesn't want to use `ShowDialog()` which is the answer that post is suggesting. – DekuDesu May 22 '21 at 17:48
  • @Jim, Have you tried using a syncronization primitive like a [Semaphore](https://learn.microsoft.com/en-us/dotnet/api/system.threading.semaphoreslim?view=net-5.0) with `await semaphore.WaitAsync()` to force the thread to wait for the modal popup? Edit: this is if events aren't working for some reason due to timing. – DekuDesu May 22 '21 at 17:50
  • @OlivierRogier I cannot use ShowDialog(). This is the previous solution which freezes the main UI – Jim May 22 '21 at 17:50
  • 2
    In general, to execute code when a `Form` object is closed, you can subscribe to the `Closed` event. See first duplicate. In that approach, you'd just put the following code into the event handler itself. If you want to express the logic using `async`/`await`, because for example you want to be able to _return_ something later, then you can use `TaskCompletionSource`, setting the completion in the `Closed` event handler, awaiting that source's task, and then returning from the now-`async` method whatever data you want when it's done. See second duplicate. – Peter Duniho May 22 '21 at 17:53
  • @DekuDesu I am afraid semaphore will not help here. – Jim May 22 '21 at 18:07
  • @OlivierRogier please checkout the sample code. I do not want just to see when the form is closed, but also get the result from that form.. In the below answer the code will not achieve this – Jim May 22 '21 at 18:10
  • @PeterDuniho do you have any suggestion with async/await approach. I am looking at this currently but no success. – Jim May 22 '21 at 18:11
  • 1
    _"no success"_ is not a useful problem description. The [second duplicate](https://stackoverflow.com/questions/12858501/is-it-possible-to-await-an-event-instead-of-another-async-method) has clear examples for convert a method like your `OnButtonClick()` into an `async` method that uses `TaskCompletionSource` to await an event like `Closed`. Follow those examples. If you have trouble, post a new question where you've provided a proper [mcve] and a detailed explanation of what the code does, how that's different from what you want, and what _specifically_ you need help with. – Peter Duniho May 22 '21 at 18:13
  • @PeterDuniho thank you for your assistance. Although, I feel that both suggested answers does not provide the necessary information to resolve the question. – Jim May 22 '21 at 18:21
  • The question is filed as `duplicate` although I would argue that none of the answers relates to the question. – Jim May 22 '21 at 18:26
  • 1
    _"I feel that both suggested answers does not provide the necessary information to resolve the question"_ -- I guarantee you that they do. The first is entirely sufficient taking your question literally, and the second duplicate provides the best way to extend the first answer to address the scenario that appears to be applicable here, given the little teensy tiny amount of code you shared. – Peter Duniho May 22 '21 at 18:34
  • @OlivierRogier this approach still blocks the Main UI so probably not the best solution – Jim May 22 '21 at 18:35
  • 1
    @Jim What's blocking what? Did you try? So what to do? You have rejected all the suggestions (callback, task, async, semaphore, conditional variable, doevents...), and especially since you have not indicated if the source window, beyond the freeze you are complaining about, must continue to be interactive or not. –  May 22 '21 at 18:38
  • @OlivierRogier no need to get upset :) I have tried many things before posting this question. By the way I have not rejected the async method and trying to make this work. The main UI must be interactive whilst the user interacts with the popup Form. – Jim May 22 '21 at 18:43
  • @Jim Thus use a callback, otherwise while (bool) doevents + (sleep[|delay])... both work fine even if the latter is not liked (the former actually uses the second technology in WinForms, so to speak , but it is better and smoother). –  May 22 '21 at 18:46

1 Answers1

0

You can attach to the FormClosed event:

        private void button1_Click(object sender, EventArgs e)
        {
            var form = new Form2();            
            form.FormClosed += Form_FormClosed;
            form.Show();
        }

        private void Form_FormClosed(object sender, FormClosedEventArgs e)
        {
            MyObject results = (sender as Form2).MyCustomResults;
            MessageBox.Show(results.ToString());
        }

You should probably also check the value of e.CloseReason

umberto-petrov
  • 731
  • 4
  • 8
  • 1
    Unfortunately this does not answer the question. Please checkout the code in the question. The next line after form.Show will be excecuted without waiting for FormClosed event. – Jim May 22 '21 at 18:07
  • 1
    well yes you need to move your "next line" to Form_FormClosed, which I did in my answer – umberto-petrov May 22 '21 at 18:08
  • I am afraid I cannot do that as it is part of larger excecution code and it must stay there. – Jim May 22 '21 at 18:10
  • _"which I did in my answer"_ -- no, actually you implemented a method completely different from the OP's original `OnButtonClick()` method, and added _completely different code_ which uses a `MessageBox` to display `results.ToString()`, instead of _returning_ the result from the method as the original code does. Not only have you made the unwarranted assumption that `MyObject` overrides `ToString()`, there's nothing here that would show how the original `OnButtonClick()` method should return the `results` value. – Peter Duniho May 22 '21 at 18:15
  • Bottom line: this answer doesn't provide any information new to the Stack Overflow web site, nor does it provide any information that is directly applicable to the OP's question. – Peter Duniho May 22 '21 at 18:16