如何在WPF上运行异步任务而不挂GUI

时间:2019-03-11 09:38:51

标签: c# wpf task invoke dispatcher

我有用于监视数据的WPF应用程序,我在Loaded方法中编写了Task.Run,以在GUI中工作并显示数据。

代码如下:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{

        await Task.Run(() => DoAddAsync());
}

void DoAddAsync()
{

  while (true)

  {
       this.Dispatcher.Invoke(() =>
       {
              //Do Some
       });
  }
}

它工作正常,我可以在不挂起的情况下更改GUI中的组件。

但是,如果我在this.Dispatcher.Invoke中执行一个方法,则GUI会挂起,直到该方法关闭,我才能做任何事情。

任何人都可以帮助我在this.Dispatcher.Invoke中运行方法而无需挂起GUI吗?

1 个答案:

答案 0 :(得分:1)

您可以使用异步循环。即使这看起来像一个无限循环,也并非如此。由于延迟Task的等待,此方法会定期将控制权交还给其调用者。如果这不是具有有效异步操作的异步方法,则它将是同步方法,并且在调用UI时会死锁UI。

但是由于它不是,所以它可以根据需要工作,并且使您既清楚了代码应该做什么的意图,又使我们始终保持在UI线程上(等待的神奇之处!),所以我们没有多线程问题或多个委托/回调。

from selenium.webdriver.support import ui
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException

url = "https://www.google.com/search?q=table&tbm=isch&source=lnt&tbs=sur:fc&sa=X&ved=0ahUKEwjVgKaq097gAhW7TBUIHd47DvkQpwUIIA&biw=1280&bih=933&dpr=1"

driver = webdriver.Firefox()
page=driver.get(url)
try:
    mySelectElement = WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.ID, "smb")))
    print(len(driver.page_source))
    mySelectElement.click()
except TimeoutException as ex:
    isrunning = 0
    print("Exception has been thrown. " + str(ex))
    driver.close()
    pass  

不过,实现此目的的真正诀窍不在DoAddAsync方法中。这就是我们所说的。您不必等待呼叫。

private async Task DoAddAsync()
{
    while (true)
    {
        // do the work in the loop
        // ....
        // don't run again for at least 200 milliseconds
        await Task.Delay(200);
    }
}

您也可以更新自己的方式,但是它会引入多个委托,这取决于所完成的工作,可能会导致多线程的复杂性,我们仍然必须回到UI线程来更新UI。

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
     DoAddAsync()
}