我有一个名为ProxyTesterForm的主表单,它有一个子表单ProxyScraperForm。当ProxyScraperForm抓取新代理时,ProxyTesterForm通过异步测试处理事件,并在测试后将代理添加到绑定列表中,该列表是DataGridView的数据源。
因为我正在添加到在UI线程上创建的数据绑定列表中,所以我正在对DataGridView调用BeginInvoke,以便更新发生在适当的线程上。
如果在下面发布的方法中没有BeginInvoke调用,我可以在处理过程中在屏幕上拖动表单而不会卡顿并且很流畅。调用BeginInvoke后,它则相反。
我有一些想法来解决这个问题,但想听听比我更聪明的人在SO上的意见,以便我能正确解决它。
因为我正在添加到在UI线程上创建的数据绑定列表中,所以我正在对DataGridView调用BeginInvoke,以便更新发生在适当的线程上。
如果在下面发布的方法中没有BeginInvoke调用,我可以在处理过程中在屏幕上拖动表单而不会卡顿并且很流畅。调用BeginInvoke后,它则相反。
我有一些想法来解决这个问题,但想听听比我更聪明的人在SO上的意见,以便我能正确解决它。
Use a semaphore slim to control the amount of simultaneous updates.
Add asynchronously processed items to a list outside of the scope of the the method I will post below, and iterate over that list in a Timer_Tick event handler, calling BeginInvoke for each item in the list every 1 second, then clearing that list and wash, rinse, repeat until the job is done.
Give up the convenience of data binding and go virtual mode.
Anything else someone might suggest here.
private void Site_ProxyScraped(object sender, Proxy proxy) { Task.Run(async () => { proxy.IsValid = await proxy.TestValidityAsync(judges[0]); proxiesDataGridView.BeginInvoke(new Action(() => { proxies.Add(proxy); })); }); }
Task.Run
。相反,将Site_ProxyScraped
改为异步,因为我假设这是一个事件处理程序。然后等待proxy.TestValidtiyAsync
,而 BeginInvoke 可以保持不变。 - FCinproxy.IsValid = await proxy.TestValidityAsync(judges[0]);
的结果存储在一个Dictionary
或Collection
中。这样会非常快速,而且不需要与 UI 进行交互。然后您可以考虑更新 UI。也许使用 500ms 的时间间隔定时器之类的东西。您可以从Dictionary
或Collection
更新 UI。 - Stefan