我创建了以下扩展方法,以便在使用WebBrowser
控件时等待页面加载。
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;
}
我有几个问题:
如果有的话,定时器何时停止存在并获得GC?我想同样的问题适用于lambda表达式。
如果目前的答案永远不会,我能做些什么来确保在不再需要的时候清理它们?
最后,ReSharper在implicitly captured closure
和navigatingHandler
定义上给了我一个documentCompletedHandler
。我怎样才能防止这种情况发生?
答案 0 :(得分:0)
非常棘手的问题。
在您返回的任务完成之前,您的计时器不会被垃圾收集。
为什么呢?好的,这是棘手的部分。那是因为关闭ReSharper正在告诉你的事情!
lambda中使用的所有变量都由框架保持活动,并引用它以确保它们在执行lambda时存在并恢复它们以供它使用。因为你在lambda中使用了计时器,所以当lambda存在时,计时器将保持活动状态,并且lambda将至少存在,直到lambda的最后一行被执行,设置任务的结果。
所以它确定假定计时器将保持活着,直到lambda被执行。