Dan*_*iel 1 c# wpf multithreading async-await
我很擅长使用C#进行线程处理.我有一个Searchfield,它会在按下的每个Key上触发针对API的HTTP-Request.在请求之后,Searchresult显示在我的SearchTab中的ListView中.当然,这会冻结UI几毫秒,直到HTTP-Request完成.所以我试着让Request Async.
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;
}
Run Code Online (Sandbox Code Playgroud)
这段代码使它更好一些,但它仍然冻结了UI,因为在某些时候它必须等待API调用.我希望能够在不中断的情况下平滑地键入我的搜索,并在进行另一次搜索(KeyPressed)之前及时完成API调用时显示结果.
你如何在C#中解决这样的问题?在JAVA中,我将使用AsyncWorker,它在搜索完成后调用Display方法(或者如果进行另一次搜索则取消worker),这样就不会在Main-Thread中进行搜索和显示.
C#中是否有类似的结构?如果我搜索多线程,我只能找到异步等待解决方案.或者可以按照我希望的方式使用它.
Task.FromResult在给定结果的情况下创建已经成功的任务.在您的示例中,结果来自对调用tmdbClient.SearchMovie().我认为这个电话是封锁的.
此代码并非真正异步,因为您仍在等待阻塞调用.您需要该tmdbClient.SearchMovie()方法的异步版本.通常,这些是显而易见的,因为它们是后缀Async.所以,你需要一个类似的方法tmdbClient.SearchMovieAsync().
如果客户端库未提供此类方法,则需要将阻塞调用转换为异步调用.
一个简单但有缺陷且有问题的方法是使用Task.Run:
(这是未经测试的伪代码)
Task<SearchContainer<SearchMovie>> searchMovie(String query)
{
return Task.Run(() => tmdbClient.SearchMovie(query, "de"));
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是你使用一个线程进行网络IO调用,这是一种不好的资源使用:后台线程正在等待阻塞调用的结果,并且在阻塞调用完成之前不能用于任何事情.它应该为您提供响应更快的UI,但具有与线程相同的线程资源成本,但异步的复杂性.
| 归档时间: |
|
| 查看次数: |
402 次 |
| 最近记录: |