首页 新闻 会员 周边

asp.net mvc 使用async的问题。

0
悬赏园豆:60 [待解决问题]

在asp.net mvc中使用async的时候遇到一个问题,请教下大家。下面是示例,

  public class HomeController : Controller
    {
        public ActionResult Index()
        {
            TestTask();

            return View();
        }


        private async Task TestTask()
        {
            try
            {
                WebRequest request = WebRequest.CreateHttp("http://localhost:4113/");//这个页面请求需要消耗5秒时间
                request.Method = "Get";
                var response = await request.GetResponseAsync().ConfigureAwait(true);

                Debug.Write("异步外面执行");
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }

我的目的是这样的,当页面执行index controller的时候会异步去访问一个远程页面(这个页面获取需要5秒钟),然后此时在这个异步还未结束的时候,index已经执行完毕,页面也已经展示出来。

接着过了几秒钟,远程访问的异步执行结束了,按照我的设计,根据这句代码 xxx.ConfigureAwait(true),目的是想让异步结束后,在返回到之前的上下文(http 线程),继续执行,所以在这句Debug.Write代码里面打了断点看看能否执行下去,但是发现断点根本没有进来,我以为是之前的上下文已经不存在,无法获取,应该抛出异常,然后我又在异常里面打了断点,依然没有进入。

 

问题描述完了,不知道有没有园友能帮忙解释下。

SuperJoe的主页 SuperJoe | 初学一级 | 园豆:68
提问于:2015-11-02 09:09
< >
分享
所有回答(2)
0

看看你的代码死锁了没有,我看你的代码不是完全异步的代码,await与ConfigureAwait(false)可以避免死锁,把(true)改为false试试,阻塞时,所有异常都会用 AggregateException 包装后引发,不知道你的全局 try/catch 可以捕获到不,我的mvc都用ajax进行异步处理了,你这种服务器异步方式我用的也太少了,以前silverlight用过会

稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-02 13:34

true改为false,肯定是没有问题的。我就是不明白,为什么我设置true之后,异步后面的代码不执行,并且也没有捕捉到异常。这个才是我疑惑的地方。

支持(0) 反对(0) SuperJoe | 园豆:68 (初学一级) | 2015-11-02 14:30

@SuperJoe: 你的代码没有完全异步,死锁了

支持(0) 反对(0) 稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-02 14:40

@稳稳的河: 哪个地方,请给指出,谢谢。

支持(0) 反对(0) SuperJoe | 园豆:68 (初学一级) | 2015-11-02 14:41

@SuperJoe: 你这样当然死锁,你想用上下稳,这种写法完全错误,必须用ConfigureAwait(false),.net的AspNetSynchronizationContext,只能被一个线程独占

public class HomeController : Controller
    {
        public ActionResult Index()
        {
            TestTask();//线程A阻塞,等待TestTask返回

            return View();
        }


        private async Task TestTask()
        {
            try
            {
                WebRequest request = WebRequest.CreateHttp("http://localhost:4113/");//这个页面请求需要消耗5秒时间-----//你在内部开闭新线程
                request.Method = "Get";
                var response = await request.GetResponseAsync().ConfigureAwait(true);

                Debug.Write("异步外面执行");
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
支持(0) 反对(0) 稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-02 15:18

@稳稳的河: var response = await request.GetResponseAsync().ConfigureAwait(false);是我知道的解决办法,服务端异步也去看的少,clr via c#里面讲了原理,有时间你去看下,我没有你需要获取上下文的解决办法

支持(0) 反对(0) 稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-02 15:22

@稳稳的河: 在下面这种情况下,异步之后是可以夺回上下文继续执行的,

异步方法执行的很快,当异步方法执行完毕之后,之前的Http线程还没有执行完毕,可以简单理解成Index action还没有执行完毕,这个时候是可以夺回上下文继续执行异步后面的代码,也就是那句Debug代码。

所以不存在死锁。

支持(0) 反对(0) SuperJoe | 园豆:68 (初学一级) | 2015-11-02 16:46

@SuperJoe: 那他的是什么问题,他这是.netmvc的程序,窗口程序本来就不会存在死锁的问题,它有线程池来处理,Debug.Write("异步外面执行");是怎么夺回的?我不怎么明白,请教下

支持(0) 反对(0) 稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-02 17:28

@SuperJoe: 你的TestTask()是在等待结果,这是一个线程,WebRequest.CreateHttp("http://localhost:4113/")也是一个线程,不被占用?当异步方法执行完毕之后,之前的Http线程还没有执行完毕?你的Http线程都是在异步方法里面,我不明白了

支持(0) 反对(0) 稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-02 17:32

@稳稳的河: TestTask根本没有阻塞,调用这句代码的时候就返回了task, var response = await request.GetResponseAsync().ConfigureAwait(true); 如果我把Index里面代码改成这样:  TestTask().GetAwaiter().GetResult();, 那才会形成死锁。

支持(0) 反对(0) SuperJoe | 园豆:68 (初学一级) | 2015-11-03 08:07

@SuperJoe:哦,调试的结果为准

支持(0) 反对(0) 稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-03 09:47

@稳稳的河: 我测试过了。呵呵。

支持(0) 反对(0) SuperJoe | 园豆:68 (初学一级) | 2015-11-03 09:59
0

对异步 了解不多,也就猜测看下。

感觉像是主线程没有正确等待异步的回应而结束。而异步过程虽然正常执行,但没有成功返回到主线程中。

 

LZ 试试TestTask()增加返回值,从response中获取一个返回的响应值,来确认下是否能主线程能正常得到回馈。

Sky.Grain | 园豆:308 (菜鸟二级) | 2015-11-17 20:50
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册