Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “试图理解”;普通的;与ASP.NET和HttpClient()的异步死锁_C#_Asp.net_Asynchronous_Async Await - Fatal编程技术网

C# “试图理解”;普通的;与ASP.NET和HttpClient()的异步死锁

C# “试图理解”;普通的;与ASP.NET和HttpClient()的异步死锁,c#,asp.net,asynchronous,async-await,C#,Asp.net,Asynchronous,Async Await,在遇到“常见”异步死锁并从中获得进一步了解后,我尝试在ASP.NET中模拟这个问题,试图找出为什么我们以前从未遇到过这个问题。看起来不同的是,以前我们使用的是http客户机get ASYC方法,这并没有引起问题 public class DeadLockController : ApiController { /// <summary> /// Does not result in deadlock - but why?

在遇到“常见”异步死锁并从中获得进一步了解后,我尝试在ASP.NET中模拟这个问题,试图找出为什么我们以前从未遇到过这个问题。看起来不同的是,以前我们使用的是http客户机get ASYC方法,这并没有引起问题

    public class DeadLockController : ApiController
    {
        /// <summary>
        /// Does not result in deadlock - but why?
        /// </summary>
        [HttpGet]
        public IHttpActionResult HttpDeadLock()
        {
            var client = new HttpClient();
            return Ok( client.GetStringAsync( "https://www.google.com/" ).Result );
        }

        /// <summary>
        /// Results in expected repeatable deadlock.
        /// </summary>
        [HttpGet]
        public IHttpActionResult DeadLock()
        {
            var delayTask = DelayAsync().Result;

            return Ok( delayTask );
        }

        /// <summary>
        /// Does not result in deadlock.
        /// </summary>
        [HttpGet]
        public async Task< IHttpActionResult > FixedDeadLock()
        {
            var delayTask = await DelayAsync();

            return Ok( delayTask );
        }

        private async Task< int > DelayAsync()
        {
           await Task.Delay( 1000 );
           return 0;
        }
    }
公共类死锁控制器:ApiController
{
/// 
///不会导致死锁-但为什么?
/// 
[HttpGet]
公共IHttpActionResult HttpDeadLock()
{
var client=新的HttpClient();
返回Ok(client.GetStringAsync(“https://www.google.com/(a)结果);
}
/// 
///导致预期的可重复死锁。
/// 
[HttpGet]
公共IHttpActionResult死锁()
{
var delayTask=DelayAsync().Result;
返回Ok(延迟任务);
}
/// 
///不会导致死锁。
/// 
[HttpGet]
公共异步任务FixedReadLock()
{
var delayTask=await DelayAsync();
返回Ok(延迟任务);
}
专用异步任务DelayAsync()
{
等待任务。延迟(1000);
返回0;
}
}
因此,如果要调用
api/DeadLock/DeadLock
,就会遇到本文中描述的常见死锁。这是预期的/理解的
api/DeadLock/FixedDeadLock
是解决这个问题的“正确”方法


然而,调用
api/DeadLock/HttpDeadLock
不会导致死锁,即使它们在概念上是相同的,我不知道为什么?为什么HttpClient没有遇到这个问题?理论上,Httpclient正在内部进行等待

api/DeadLock/HttpDeadLock不是死锁的原因是,在该代码中,您没有等待任何任务

而是通过调用task.Result同步等待任务来阻塞线程


在实现这种模式时,死锁通常会出现async await和Task.Wait/Task.Result组合。

将DelayAsync更改为
await Task.Delay(1000)。ConfigureAwait(false)api/DeadLock/DeadLock
也不会再出现死锁。请阅读文章的“配置上下文”部分以获得一些解释。@ScottChamberlain谢谢-您也可以像我在FixedDeadLock()中所做的那样,使用wait来修复它函数也来源于那篇文章,因为上下文-问题是为什么HttpClient不会导致此问题?仅供参考-不是您问题的答案,但您应该阅读:出于好奇,您如何可靠地重现
api/deadlock/deadlock
?i、 e.您是否有100个并发请求?内部
HttpClient
一直都有
.ConfigureAwait(false)
,以防止出现“不正确”的问题使用库如果每次点击api/deadlock/deadlock,它都会因为死锁而挂起。我想强调的一个关键点是,
GetStringAsync
在内部不使用
Wait
,生成任务的
TaskCompletionSource
,然后只返回任务。@ScottChamberlain注释就是我想要的答案:)Thanks@ScottChamberlain我想说,真正的关键是它不会将其延续发布到当前的同步上下文中。(无需使用
await
即可完成,或者即使使用
await
也可以避免)