c#奇怪的语法

参考微软网页:

使用 Async 和 Await 的异步编程 (C#)
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index

演练:使用 Async 和 Await 访问 Web (C#) 
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/walkthrough-accessing-the-web-by-using-async-and-await

await(C# 参考)
https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/await

今天做async await实验时发现一个奇怪的语法现象:

static void test()
{
       Console.WriteLine("asyncawaittest");
 }
private void btnasyncawait_Click(object sender, EventArgs e)
 {
       new Thread(test) { IsBackground = true }.Start(); //**注意** IsBackground = true后面没有分号“;”
       //new Thread(test) { IsBackground = true, Name = "mythreadname" }.Start(); //也成功
 }

以上代码成功,改成如下代码也成功:

static void test()
{
       Console.WriteLine("asyncawaittest thread id = "+Thread.CurrentThread.ManagedThreadId+" thread name="+Thread.CurrentThread.Name);
 }
private void btnasyncawait_Click(object sender, EventArgs e)
 {
       Console.WriteLine("main thread id = " + Thread.CurrentThread.ManagedThreadId);
       new Thread(test) { IsBackground = true, Name = "mythreadname" }.Start();//**注意**
 }

但在true后面加上一个分号之后出现语法错误。后来通过学习才明白这种用法在叫做“对象初始化器”,比如:

Person person = new Person();
person.Name = "Slark";
person.Age = 100;
person.Address = "Xi'an";

这里我们用了一行创建对象语句,加三行赋值语句。这里光person这个变量就出现了4遍,繁琐。用对象初始化器来代替这些操作:

Person person = new Person { Name = "Slark", Age = 100, Address = "Xi'an" };

c#中除了对象初始化器之外,还有集合初始化器:

List<int> intList = new List<int>();
intList.Add(1);
intList.Add(2);
intList.Add(3);
好,这里我们用4行代码创建了一个3个元素的集合。集合初始化器的出现大大减少了我们对这种操作的代码量。其对应的集合初始化器代码为:

List<int> intList = new List<int> { 1, 2, 3 };

下面来真正进入async和await学习中来,先看一段代码:

 private void btnasyncawait_Click(object sender, EventArgs e) 
        {
            Console.WriteLine("main thread id = " + Thread.CurrentThread.ManagedThreadId);
            Say();
        }
        private async static void Say()
        {
            Console.WriteLine("Say thread id = " + Thread.CurrentThread.ManagedThreadId);
            var t = TestAsync();
            Thread.Sleep(1100);                                     //主线程在执行一些任务
            Console.WriteLine("Main Thread");                       //主线程完成标记
            Console.WriteLine(await t);                             //await 主线程等待取异步返回结果
        }
        static async Task<string> TestAsync()
        {
            return  await Task.Run(() =>
            {
                Console.WriteLine("await task thread id = " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(1000);                                 //异步执行一些任务
                return "Hello World";                               //异步执行完成标记
            });
        }

以上代码可以成功运行,点击按钮再次,结果如下:

main thread id = 8
Say thread id = 8
await task thread id = 9
Main Thread
Hello World
main thread id = 8
Say thread id = 8
await task thread id = 9
Main Thread
Hello World

去掉TestAsync()中的async和await即代码如下时:

        static  Task<string> TestAsync()
        {
            return  Task.Run(() =>
            {
                Console.WriteLine("await task thread id = " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(1000);                                 //异步执行一些任务
                return "Hello World";                               //异步执行完成标记
            });
        }

代码也能成功运行,点击按钮再次,结果如下:

main thread id = 8
Say thread id = 8
await task thread id = 9
Main Thread
Hello World
main thread id = 8
Say thread id = 8
await task thread id = 10
Main Thread
Hello World

当我将代码修改如下时,发现一个很不明白的现象(主要是将Say()函数中的t之前的await去掉了):

private void btnasyncawait_Click(object sender, EventArgs e) 
        {
            Console.WriteLine("main thread id = " + Thread.CurrentThread.ManagedThreadId);
            Say();
        }
        private async static void Say()
        {
            Console.WriteLine("Say thread id = " + Thread.CurrentThread.ManagedThreadId);
            var t = TestAsync();
            Thread.Sleep(1100);                                     //主线程在执行一些任务
            Console.WriteLine("Main Thread");                       //主线程完成标记
            Console.WriteLine( t);                             //注意此处t之前没有await
        }
        static async Task<string> TestAsync()
        {
            return await Task.Run(() =>
            {
                Console.WriteLine("await task thread id = " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(1000);                                 //异步执行一些任务
                return "Hello World";                               //异步执行完成标记
            });
        }

打印出来的结果为:

main thread id = 10
Say thread id = 10
await task thread id = 11
Main Thread
System.Threading.Tasks.Task`1[System.String]

再将代码修改如下:

private void btnasyncawait_Click(object sender, EventArgs e) 
        {
            Console.WriteLine("main thread id = " + Thread.CurrentThread.ManagedThreadId);
            Say();
        }
        private async static void Say()
        {
            Console.WriteLine("Say thread id = " + Thread.CurrentThread.ManagedThreadId);
            var t = TestAsync();
            Thread.Sleep(1100);                                     //主线程在执行一些任务
            Console.WriteLine("Main Thread");                       //主线程完成标记
            Console.WriteLine( t);                             
        }
        static Task<string> TestAsync()
        {
            return Task.Run(() =>
            {
                Console.WriteLine("await task thread id = " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(1000);                                 //异步执行一些任务
                return "Hello World";                               //异步执行完成标记
            });
        }

打印结果如下:

main thread id = 9
Say thread id = 9
await task thread id = 10
Main Thread
System.Threading.Tasks.Task`1[System.String]

还有一段测试代码如下:

private void trfun()
        {
            var ttr = Task.Run<String>(() =>
            {
                Thread.Sleep(3000);
                return "abc";
            });
            string rs = ttr.Result;//阻塞3秒
            Console.WriteLine("ttr.result=" + rs);
        }

主程序中调用trfun()函数,则主程序要等待大约3秒钟之后才打印出结果abc之后才往下执行。换成如下代码:

        private void btnasyncawait_Click(object sender, EventArgs e) 
        {
            Console.WriteLine("main thread id = " + Thread.CurrentThread.ManagedThreadId);
            trfun();            
            Say();
        }
        private async void trfun()
        {
            var ttr = Task.Run<String>(() =>
            {
                Thread.Sleep(3000);
                return "abc";
            });
           
            string rs = await ttr;//当程序执行到此句时不会再向下反而是快速进入btnasyncawait_Click中的Say()
            Console.WriteLine("trfun thread id = " + Thread.CurrentThread.ManagedThreadId);//此句需要等3秒才能执行,且处于主线程ID中
            Console.WriteLine("ttr.result=" + rs);
        }

打印出来的结果如下:

main thread id = 9
Say thread id = 9
await task thread id = 11
Main Thread
Hello World
trfun thread id = 9
ttr.result=abc

这种异步处理对于btnasyncawait_Click及其主线程来说不会阻塞,阻塞的只是trfun中的await ttr语句。

还有一篇帖子 C#Winform里的async和await异步 https://blog.csdn.net/liuqianggege1/article/details/48135301 讲得也不错

 1个按钮,2个textbox,下面这样可以正确异步,窗体也不会死掉,textBox2会先有结果,textBox1再有结果

    private async void button1_Click(object sender, EventArgs e)

        {
            Does();
            textBox2.Text = "1";
        }


        private Task<string> DoWork()
        {
            return Task.Run(() =>
               {
            Thread.Sleep(4000);
            return "Done with work!";
               }
                );
        }
        private async void Does()
        {
            string text = await DoWork();
            textBox1.Text = text;
        }

如果把按钮事件改成下面这样,窗体不会死,但不会异步执行

   private async void button1_Click(object sender, EventArgs e)

        {
            textBox2.Text =await DoWork();
            textBox2.Text = "1";
        }

转载于:https://my.oschina.net/u/2963604/blog/1819331

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值