asyne,await,task.wait,task.result用法

asyne,await,task.wait,task.result用法


首先看下面的代码:
class Program
{
    static void Main(string[] args)
    {
        TestTask();
    }
}


private async void TestTask()
        {
            Console.WriteLine("step1,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            AsyncDemo demo = new AsyncDemo();
            //var result = demo.AsyncSleep().Result;//.Result会阻塞当前线程直到AsyncSleep返回
			//demo.AsyncSleep().Wait();//Wait会阻塞当前线程直到AsyncSleep返回
            //Console.WriteLine(result);
            demo.AsyncSleep();//不会阻塞当前线程
            
            Console.WriteLine("step5,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
		
public class AsyncDemo
    {
        public async Task<string> AsyncSleep()
        {
            Console.WriteLine("step2,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            //await关键字表示“等待”Task.Run传入的逻辑执行完毕,此时(等待时)AsyncSleep的调用方能继续往下执行(准确地说,是当前线程不会被阻塞)
            //Task.Run将开辟一个新线程执行指定逻辑
            var result = "";
            //result = await Task.Run(() => Sleep(10)).ConfigureAwait(false);
            await Task.Run(() => Sleep(10));
            Console.WriteLine("step4,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            return result;
        }


        private string Sleep(int second)
        {
            Console.WriteLine("step3,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            Thread.Sleep(second * 1000);
            return "sleep";
        }
    }

运行结果:
step1,
step2,
step3,
step5,
step4,


修改下代码如下:
private async void TestTask()
        {
            Console.WriteLine("step1,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            AsyncDemo demo = new AsyncDemo();
            //var result = demo.AsyncSleep().Result;//Result会阻塞当前线程直到AsyncSleep返回
            demo.AsyncSleep().Wait();   //Wait会阻塞当前线程直到AsyncSleep返回
            //Console.WriteLine(result);
            //demo.AsyncSleep();//不会阻塞当前线程
            
            Console.WriteLine("step5,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
		
public class AsyncDemo
    {
        public async Task<string> AsyncSleep()
        {
            Console.WriteLine("step2,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            //await关键字表示“等待”Task.Run传入的逻辑执行完毕,此时(等待时)AsyncSleep的调用方能继续往下执行(准确地说,是当前线程不会被阻塞)
            //Task.Run将开辟一个新线程执行指定逻辑
            var result = "";
            //result = await Task.Run(() => Sleep(10)).ConfigureAwait(false);
            await Task.Run(() => Sleep(10));
            Console.WriteLine("step4,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);

            return result;
        }

        private string Sleep(int second)
        {
            Console.WriteLine("step3,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            Thread.Sleep(second * 1000);
            return "sleep";
        }
    }

运行结果如下:
step1,
step2,
step3,

step4,step5出不来了,程序死锁

再修改下代码如下:
private async void TestTask()
        {
            Console.WriteLine("step1,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            AsyncDemo demo = new AsyncDemo();
            //var result = demo.AsyncSleep().Result;//Result会阻塞当前线程直到AsyncSleep返回
            demo.AsyncSleep().Wait();   //Wait会阻塞当前线程直到AsyncSleep返回
            //Console.WriteLine(result);
            //demo.AsyncSleep();//不会阻塞当前线程
            
            Console.WriteLine("step5,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
    public class AsyncDemo
    {
        public async Task<string> AsyncSleep()
        {
            Console.WriteLine("step2,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            //await关键字表示“等待”Task.Run传入的逻辑执行完毕,此时(等待时)AsyncSleep的调用方能继续往下执行(准确地说,是当前线程不会被阻塞)
            //Task.Run将开辟一个新线程执行指定逻辑
            var result = "";
            result = await Task.Run(() => Sleep(10)).ConfigureAwait(false);
            //await Task.Run(() => Sleep(10));
            Console.WriteLine("step4,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            return result;
        }


        private string Sleep(int second)
        {
            Console.WriteLine("step3,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            Thread.Sleep(second * 1000);
            return "sleep";
        }
    }
      
运行结果:
step1,
step2,
step3,
step4,
step5,


代码再修改如下:
private async void TestTask()
        {
            Console.WriteLine("step1,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            AsyncDemo demo = new AsyncDemo();
            var result = demo.AsyncSleep().Result;//Result会阻塞当前线程直到AsyncSleep返回
            //demo.AsyncSleep().Wait();   //Wait会阻塞当前线程直到AsyncSleep返回
            //Console.WriteLine(result);
            //demo.AsyncSleep();//不会阻塞当前线程
            
            Console.WriteLine("step5,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
    public class AsyncDemo
    {
        public async Task<string> AsyncSleep()
        {
            Console.WriteLine("step2,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            //await关键字表示“等待”Task.Run传入的逻辑执行完毕,此时(等待时)AsyncSleep的调用方能继续往下执行(准确地说,是当前线程不会被阻塞)
            //Task.Run将开辟一个新线程执行指定逻辑
            var result = "";
            result = await Task.Run(() => Sleep(10)).ConfigureAwait(false);
            //await Task.Run(() => Sleep(10));
            Console.WriteLine("step4,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            return result;
        }


        private string Sleep(int second)
        {
            Console.WriteLine("step3,线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);


            Thread.Sleep(second * 1000);
            return "sleep";
        }
    }

运行结果:
step1,
step2,
step3,
step4,
step5,

所在当用 .Wait()或者.Result 调用async方法时,如果async方法内有 await 调用其它方法时,会产生死锁,可以用await Task.Run(() => Sleep(10)).ConfigureAwait(false);
即加上.ConfigureAwait(false),可以解决死锁问题

所以推荐的用法是当需要等待结果里 用 await 方式调用。

 .ConfigureAwait

尝试将延续任务封送回原始上下文,则为 true;否则为 false。

对ConfigureAwait的了解:

1)当ConfigureAwait(true),代码由同步执行进入异步执行时,当前同步执行的线程上下文信息(比如HttpConext.Current,Thread.CurrentThread.CurrentCulture)就会被捕获并保存至SynchronizationContext中,供异步执行中使用,并且供异步执行完成之后(await之后的代码)的同步执行中使用(虽然await之后是同步执行的,但是发生了线程切换,会在另外一个线程中执行「 ASP.NET场景」)。这个捕获当然是有代价的,当时我们误以为性能问题是这个地方的开销引起,但实际上这个开销很小,在我们的应用场景不至于会带来性能问题。

2)当Configurewait(flase),则不进行线程上下文信息的捕获,async方法中与await之后的代码执行时就无法获取await之前的线程的上下文信息,在 ASP.NET中最直接的影响就是HttpConext.Current的值为null。 

参考: http://www.cnblogs.com/newton/archive/2013/05/13/3075039.html

https://msdn.microsoft.com/zh-cn/magazine/jj991977.aspx 

--- end ---

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值