C# 任务。运行它的工作方式
我想这很简单,但我在工作中有一些误解 当我调用下面的代码时,它工作得很好,我大约在1秒内得到一个结果C# 任务。运行它的工作方式,c#,multithreading,asynchronous,async-await,task,C#,Multithreading,Asynchronous,Async Await,Task,我想这很简单,但我在工作中有一些误解 当我调用下面的代码时,它工作得很好,我大约在1秒内得到一个结果 return Task.Run(() => SendRequest<IADsystem[]>(path)).Result; returntask.Run(()=>SendRequest(path)).Result; 但这个永远不会返回结果: Task<IADsystem[]> task = SendRequest<IADsystem[]>(pat
return Task.Run(() => SendRequest<IADsystem[]>(path)).Result;
returntask.Run(()=>SendRequest(path)).Result;
但这个永远不会返回结果:
Task<IADsystem[]> task = SendRequest<IADsystem[]>(path);
task.Wait(); //also tried without wait
return task.Result;
Task Task=SendRequest(路径);
task.Wait()//我也迫不及待地试了一下
返回任务。结果;
我想可能任务没有启动,我需要调用start(),但当我启动时,出现了“承诺式任务可能不会调用start”异常
发送请求方法:
private async Task<T> SendRequest<T>(string requestUri) where T : class
{
var authHandler = new HttpClientHandler();
authHandler.Credentials = CredentialCache.DefaultNetworkCredentials;
using(var client = new HttpClient(authHandler))
{
client.BaseAddress = apiServerURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(jsonAcceptType);
HttpResponseMessage response = await client.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsAsync<T>();
}
else
return null;
}
}
私有异步任务SendRequest(字符串requestUri),其中T:class
{
var authHandler=new-HttpClientHandler();
authHandler.Credentials=CredentialCache.DefaultNetworkCredentials;
使用(var client=newhttpclient(authHandler))
{
client.BaseAddress=apiServerURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(jsonAcceptType);
HttpResponseMessage response=wait client.GetAsync(requestUri);
if(响应。IsSuccessStatusCode)
{
return wait response.Content.ReadAsAsync();
}
其他的
返回null;
}
}
请解释它是如何工作的异步/等待方法必须始终是异步/等待的。如果您使用的是Windows窗体,则任何包含调用SendRequest的代码的事件处理程序都必须标记为async。UI事件处理程序和SendRequest之间的每个方法也必须标记为async,并且必须等待它们。那你应该
var result = await SendRequest<IADsystem[]>(path);
var result=等待发送请求(路径);
就像法比奥建议的那样
是关于async/await的更多信息。我在本页开始学习async,所以我认为这是一个很好的起点。我敦促你们看看执行上下文 说到你为什么会死锁,我会尽力解释的。调用
task.Wait()
时,基本上是告诉当前线程等待结果继续。因此,现在您的当前线程或执行上下文正在等待结果继续。让我们继续。调用task.Wait()
时,输入了private async task SendRequest(string requestUri).
方法,到达return Wait response.Content.readasasasync()的时刻
您传递了当前的执行上下文,该上下文正在等待来自SendRequest
的结果。现在,你处于死锁中。为什么?您的UI线程正在等待SendRequest
的答复,以便SendRequest
完成(或return
),它需要访问UI线程,但您无法访问UI线程,因为它正在等待SendRequest
完成,但要SendRequest
完成,它需要访问UI线程….首先考虑Wait()
方法:
Task<IADsystem[]> task = SendRequest<IADsystem[]>(path);
task.Wait(); //also tried without wait
return task.Result;
有点。它“工作”的意义是它不会死锁。但是,这并不理想,因为它会在请求期间阻塞线程池线程。更好的解决方案是始终使用async
但暂且不提这一点,它之所以有效,是因为它“走出”了调用上下文Task.Run
在线程池线程(没有UI或ASP.NET请求上下文的线程)上执行SendRequest
,因此SendRequest
中的wait
s在线程池线程上恢复。这就是为什么你的调用线程可以在没有死锁的情况下阻止它
但它仍然不应该阻碍这项任务;它应该等待它。您是否尝试过等待发送请求(路径)您的
SendRequest
方法与多线程无关。您在哪里执行它,什么环境(控制台、Winforms、WPF、ASP:NET)?如果您从您输入的UI线程调用第二个方法deadlock@Fabio,ASP NET Web表单,具有等待相同结果-永不返回此行应工作var result=wait SendRequest(路径)代码>。你说的“永不回头”是什么意思?你是如何检查这一点的
return Task.Run(() => SendRequest<IADsystem[]>(path)).Result;