-2

I initiate a search, then display the results of that search in the form.

If I use .Show() the form freezes. If I use .ShowDialog() the form shows up, but the search does not complete as control is not returned to the thread until the form is closed.

The .ShowDialog() way works on the 2nd call once the form is initialized because the initialize method calls the else activate code. But I'd like this to work on the first call.

Code is as follows.

public static void Search(string searchstring)
{
    IntializeSearchResultsForm()

    List<searchitem> templist = searchmethod(searchstring);

    SearchForm.Invoke((MethodInvoker) (() => SearchForm.SetSearchResultsData(tempList)));
}

public static void IntializeSearchResultsForm()
{
    if (SearchForm == null)
    {
        SearchForm = new SearchForm();
        SearchForm.Show(); OR SearchForm.ShowDialog();
    }
    else
    {
        SearchForm.Invoke(new MethodInvoker(SearchForm.Activate));
    }
}

UPDATE with more code details:

public static List<PricerSearchResultEntry> searchmethod(string dealID)
    {
        List<PricerSearchResultEntry> tempResultsList = new List<PricerSearchResultEntry>();

        foreach (String dir in pricerFolderArray)
        {
            if (Directory.Exists(dir))
            {
                string[] filesList = Directory.GetFiles(dir, "*" + dealID + "*");
                foreach (String file in filesList)
                {
                    if (AppContext.SearchPricersForm.PricersCheckBox)
                    {
                        if (file.Contains("pricer") && !file.Contains("Failed") && !file.Contains("Incomplete"))
                        {
                            tempResultsList.Add(ParseFileString(file));
                        }
                    }                        
                }
            }
        }

        tempResultsList.Sort((x, y) => y.ValuationDate.CompareTo(x.ValuationDate));

        return tempResultsList;
    }

public SearchForm()
    {
        InitializeComponent();

        searchResultsListBox.DisplayMember = "Title";
        searchResultsListBox.ValueMember = "DealID";
        searchResultsListBox.DataSource = searchResultsList;
    }
Hardycore
  • 334
  • 4
  • 17
  • What is your expected behavior? – Vadim Martynov Jan 06 '16 at 21:19
  • Pretty sure that 'freezing' doesn't occur in this code. What do you do in the Constructor of SearchForm, what in that Form_Load event and finally what happens in the _searchMethod_ above – Steve Jan 06 '16 at 21:20
  • Will add more code shortly, duty calls. – Hardycore Jan 06 '16 at 21:23
  • Added more code. As stated below, i believe the freezing happens due to a message loop? Not really sure what that is but its discussed in the link below. – Hardycore Jan 07 '16 at 00:48
  • In the end I just ended up pre-initing the form at startup and then hiding it and that seems to work fine. Overcoming the threading issues doesn't seem worth the hassle. – Hardycore Jan 07 '16 at 16:59

1 Answers1

3

If I use .Show() the form freezes

This indicates that your calculation uses blocking code. You need to either use a non-blocking algorithm (such as async/await) to allow the GUI to process messages, or do the calculation on a background (aka helper aka worker) thread.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • I don't believe that's the case. There is no blocking code in the search algo, its super simple. I think this question/answer explains why .show() freezes the GUI. http://stackoverflow.com/questions/11420717/form-show-called-from-a-console-freezes-the-gui – Hardycore Jan 06 '16 at 21:21
  • @Hardycore, do you mean you're trying to run `Show()` in a Console app outside of a call to `Application.Run()`? – adv12 Jan 06 '16 at 21:25
  • 1
    @Hardycore: "It's super simple" pretty much guarantees that is **is** blocking code. Code doesn't yield control to a message loop by default, it requires some effort to split it into steps that can be individually `await`-ed. – Ben Voigt Jan 06 '16 at 21:32
  • Will add search code and form init code shortly. – Hardycore Jan 06 '16 at 21:51
  • I've traced it quite thoroughly and I'm pretty sure the search and constructor aren't blocking. If they were then the .showdialog() case wouldn't work either would it? – Hardycore Jan 07 '16 at 00:50
  • @Hardycore: `ShowDialog()` itself is blocking, and cannot be blocked by other code that hasn't gotten a chance to run yet. – Ben Voigt Jan 07 '16 at 00:50
  • Ah yes, true. As i stated the search doesn't even run when showdialog is called. My bad, its been a long day. Is there anything you can see in my searching code that would be cause for concern? – Hardycore Jan 07 '16 at 00:52
  • @Hardycore: Yes, most of the time is spent in `Directory.GetFiles()` which is a blocking function. Unfortunately [there doesn't seem to be an async-enabled version](http://stackoverflow.com/questions/719020/is-there-an-async-version-of-directoryinfo-getfiles-directory-getdirectories-i) so you'll have to use a worker thread. – Ben Voigt Jan 07 '16 at 00:54
  • I've removed everything except the IntializeSearchResultsForm() call and it still freezes the form when using .show() so i think that eliminates the search as a culprit. I just tried using Application.Run(SearchForm) which yields similar results to .showdialog. Any other ideas? – Hardycore Jan 07 '16 at 01:10
  • Maybe something like `List templist = await Task.Run(() => searchmethod(searchstring));` – Ben Voigt Jan 07 '16 at 01:13
  • What triggers the search? Is this a button press/menu option in another form? Or part of a bigger operation which might block UI updates? – Ben Voigt Jan 07 '16 at 01:14
  • The initialization and subsequent search is triggered by a signalr call. The hub receives the search term, calls the static search method within the static class that contains it. What I'm thinking right now, is there a way to return control to the main thread after calling show dialog without closing the form? – Hardycore Jan 07 '16 at 01:20
  • I don't know anything about SignalR, but the basic description sounds like it's meant to be a network server, not used with a GUI. Probably you can make them work together, but you'll need different threads for the server and the GUI. – Ben Voigt Jan 07 '16 at 02:15
  • I think you might be right. In the end I just ended up pre-initing the form at startup and then hiding it and that seems to work fine. Thanks for your help Ben! – Hardycore Jan 07 '16 at 16:58