1

I have created the following extension method to wait for a page to load when using the WebBrowser control.

public static Task<bool> WaitLoad(this WebBrowser webBrowser, int wait)
    {
        var timerInternalWait = new Timer {Interval = 1000, Tag = "Internal"};
        var timerMaxWait = new Timer {Interval = wait};
        var tcs = new TaskCompletionSource<bool>();

        WebBrowserNavigatingEventHandler navigatingHandler = (sender, args) => timerInternalWait.Stop();
        webBrowser.Navigating += navigatingHandler;

        WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (sender, args) => { timerInternalWait.Stop(); timerInternalWait.Start(); };
        webBrowser.DocumentCompleted += documentCompletedHandler;

        EventHandler timerHandler = null;
        timerHandler = (sender, args) =>
        {
            webBrowser.Navigating -= navigatingHandler;
            webBrowser.DocumentCompleted -= documentCompletedHandler;
            timerInternalWait.Tick -= timerHandler;
            timerMaxWait.Tick -= timerHandler;
            timerMaxWait.Stop();
            timerInternalWait.Stop();

            tcs.SetResult(((Timer) sender).Tag.ToString() == "Internal");
        };

        timerInternalWait.Tick += timerHandler;
        timerMaxWait.Tick += timerHandler;

        return tcs.Task;
    }

I have a couple of question around it though:

When, if ever, do the timers cease to exist and get GCed? I suppose the same question applies for the lambda expressions.

And if currently the answer is never, is there something I can do to ensure that they are cleaned up when no longer needed?

Lastly, ReSharper gives me an implicitly captured closure on the navigatingHandler and the documentCompletedHandler definitions. How can I prevent this from happening?

JohnUbuntu
  • 699
  • 6
  • 19
  • If you have multiple questions then please post multiple questions. When you post many questions inside one question usually most of them don't get answered. – Eric Lippert Feb 06 '16 at 17:14
  • Also, this question very much looks like a duplicate of http://stackoverflow.com/questions/18136735/can-timers-get-automatically-garbage-collected. Does that question cover what you're asking here? – Eric Lippert Feb 06 '16 at 17:15
  • @EricLippert unfortunately that link does not quite answer my question. – JohnUbuntu Feb 06 '16 at 17:20

1 Answers1

0

Really tricky question.

Your timer won't be garbage collected until the task you returned has finished.

Why? ok, here is the tricky part. That's because of the closure ReSharper is telling you about!

All the variables used inside the lambda are kept alive by the framework with a reference to ensure they exist when the lambda is executed and to restore them for it's use. Because you are using the timer inside the lambda the timer will be kept alive while the lambda exists, and the lambda will exists at least until the last line of the lambda has been executed, setting the result of the task.

So it's sure to assume the timer will be kept alive until the lambda has been executed.

Gusman
  • 14,905
  • 2
  • 34
  • 50