【问题标题】:Async Online Search freezing WPF-UI异步在线搜索冻结 WPF-UI
【发布时间】:2016-05-12 11:23:10
【问题描述】:

我对 C# 中的线程非常陌生。我有一个搜索字段,它在每个按下的键上触发针对 API 的 HTTP 请求。在请求之后,Searchresult 将显示在我的 SearchTab 的 ListView 中。当然,这会使 UI 冻结几毫秒,直到 HTTP 请求完成。所以我尝试使请求异步。

private async void textBoxSearch_KeyUp(object sender, KeyEventArgs e)
{

    SearchTab searchTab;

    Task<SearchContainer<SearchMovie>> searchTask = searchMovie(textBoxSearch.Text);

    if (searchTabExists())
    {
        searchTab = getSearchTab();
    }
    else
    {
        searchTab = new SearchTab();
        mainTabControl.Items.Insert(mainTabControl.Items.Count, searchTab);
    }
    searchTab.IsSelected = true;

    SearchContainer<SearchMovie> results = await searchTask;
    searchTab.updateSearch(results);
}

async Task<SearchContainer<SearchMovie>> searchMovie(String query)
{
    var today = await Task.FromResult<SearchContainer<SearchMovie>>(tmdbClient.SearchMovie(query, "de"));
    return today;
}

这段代码让它变得更好了,但它仍然让 UI 冻结了一点,因为在某些时候它必须等待 API-Call。如果 API-Call 在进行另一次搜索 (KeyPressed) 之前及时完成,我希望能够流畅地键入我的搜索而不会中断并显示结果。

你如何在 C# 中解决这样的问题?在 JAVA 中,我会使用 AsyncWorker,它在搜索完成后调用 Displaymethod(或者如果进行了另一次搜索,则取消工作人员),这样搜索和显示就不会在主线程中完成。

C# 中有类似的构造吗?如果我搜索多线程,我只能找到异步等待解决方案。或者可以按照我希望的方式使用它。

【问题讨论】:

  • 我在这段代码中看不到任何异步内容。所有调用都是同步的。
  • "在 JAVA 中我会使用 AsyncWorker" 是的,.net 等效项称为 BackgroundWorker,而这正是 async/await 旨在取代的。 Task.FromResult 用于使用异步 API 进行同步工作。

标签: c# wpf multithreading async-await


【解决方案1】:

Task.FromResult 在给定结果的情况下创建一个已经成功的任务。在您的示例中,结果来自对tmdbClient.SearchMovie() 的调用。我假设这个调用被阻塞了。

此代码并不是真正的异步,因为您仍在等待阻塞调用。您需要 tmdbClient.SearchMovie() 方法的异步版本。通常,这些是显而易见的,因为它们以Async 为后缀。所以,你需要一个像tmdbClient.SearchMovieAsync() 这样的方法。

如果您的客户端库未提供此类方法,则您需要将阻塞调用转换为异步调用。

一种简单但有缺陷且有问题的方法是使用Task.Run

(这是未经测试的伪代码)

Task<SearchContainer<SearchMovie>> searchMovie(String query)
{
    return Task.Run(() => tmdbClient.SearchMovie(query, "de"));
}

这里的问题是你正在使用一个线程来做一个网络IO调用,这是对资源的一种不好的使用:后台线程正在等待阻塞调用的结果,并且在阻塞调用之前不能用于任何事情完成。它应该为您提供响应更快的 UI,但线程资源成本与线程相同,但异步的复杂性。

【讨论】:

  • 您的方法中不需要异步,您需要将委托传递给Task.Run。顺便说一句,我已经修复了你的代码。
  • @Aron 谢谢!我应该对我的伪代码更加勤奋:D
  • 你说得对,我使用的库的 Alpha 版提供异步调用。现在等待完美工作,不再冻结
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多