不支持await关键字时如何将方法改造为真正异步执行
问题根因
你当前的代码存在两个核心问题:
- 方法虽然标记了
async关键字,但方法内部没有任何await操作,编译器会抛出CS1998警告,运行时该方法实际为同步执行,调用时会直接阻塞当前线程直到client.Execute执行完成,不会提前返回Task对象 - 你使用了RestSharp的同步方法
Execute,本身就是阻塞式的IO操作,没有异步逻辑支撑
最优解决方案(推荐)
RestSharp官方提供了原生可等待的异步方法ExecuteAsync,IO密集型请求直接使用原生异步即可,不需要额外包装,不会浪费线程池资源:
private async Task<byte[]> PostRequestToOptiRoutesAsync() { string urlCallBack = u.Trim(this.URLAchzraR4M); var client = new RestClient(u.Trim(PrmtrimGlobliim_407_2.Mchrozt)); client.Timeout = -1; var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.AddParameter("hfd_xml", u.Trim(BlovXMLBkshaOPT).Replace("\r", "").Replace("\n", "").Replace("\t", "")); request.AddParameter("link", urlCallBack); // 替换为原生异步方法并await IRestResponse response = await client.ExecuteAsync(request); return u.UTF8FromAnsi(response.Content); } private async Task GetOptimalRoute() { byte[] result = await PostRequestToOptiRoutesAsync(); // 后续处理result的逻辑 }
兜底解决方案(不推荐,仅当无法使用原生异步时使用)
如果因为版本限制等原因确实无法使用ExecuteAsync,可以用Task.Run将同步阻塞操作包装到线程池线程运行,避免阻塞当前调用线程:
private async Task<byte[]> PostRequestToOptiRoutesAsync() { string urlCallBack = u.Trim(this.URLAchzraR4M); var client = new RestClient(u.Trim(PrmtrimGlobliim_407_2.Mchrozt)); client.Timeout = -1; var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.AddParameter("hfd_xml", u.Trim(BlovXMLBkshaOPT).Replace("\r", "").Replace("\n", "").Replace("\t", "")); request.AddParameter("link", urlCallBack); // 用Task.Run包装同步阻塞操作 IRestResponse response = await Task.Run(() => client.Execute(request)); return u.UTF8FromAnsi(response.Content); }
注意:该方案本质是用线程池资源换非阻塞效果,针对IO密集型操作会产生不必要的线程开销,仅做兜底使用
内容的提问来源于stack exchange,提问作者חיים חדד
相关产品推荐
相关产品推荐

