.Net并行编程(5).NET中的异步编程Async与Await

序言

.net中实现异步有两种方式,第一种是多线程的方式,第二种是使用异步函数,其实在异步函数中使用的还是多线程的技术。

.net在System.Threading和System.Threading.Tasks这两个命名空间中提供了Thread,ThreadPool,和Task三个类来处理多线程的问题,

其中Thread是建立一个专用线程,ThreadPool是使用线程池中工作线程,而Task类是采用任务的方式,其内部也是使用线程池中的工作线程。

await并非等待

async

异步调用前后可能运行在不同的线程

异步不等于多线程

yield

 

1.同步

 private void button1_Click(object sender, EventArgs e)
        {
            this.label1.Text = DoWork();
        }
        private string DoWork()
        {
            Thread.Sleep(5000);
            return "StartDo";
        }

2.异步(有返回值)

private async void button2_Click(object sender, EventArgs e)
        {
            this.label1.Text = await DoWorkAsync();
        }
        private Task<string> DoWorkAsync()
        {
            return Task.Run(() => {
                Thread.Sleep(5000);
                return "StartDo";
            });
        }

3.异步(无返回值)

 private async void button3_Click(object sender, EventArgs e)
        {
            await Task.Run(() => 
            { 
                Thread.Sleep(3000);
                MessageBox.Show("StartDo");
            });
        }

4.具有多个await的异步方法

private async void button4_Click(object sender, EventArgs e)
        {
            await Task.Run(() =>{ Thread.Sleep(3000);});
            MessageBox.Show("1");

            await Task.Run(() => { Thread.Sleep(3000); });
            MessageBox.Show("2");

            await Task.Run(() => { Thread.Sleep(3000); });
            MessageBox.Show("3");
        }

异步任务如何取消

取消令牌CancellationTokenSource

async Task底层

https://sharplab.io/

using System;
using System.Threading;
using System.Threading.Tasks;
public class C {
    public void M() {
    }
    
    public async Task Foo() {
        await Task.Delay(3000);
    }
}

底层使用了状态机

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]

public class C
{
    [CompilerGenerated]
    private sealed class <Foo>d__1 : IAsyncStateMachine
    {
        public int <>1__state;

        public AsyncTaskMethodBuilder <>t__builder;

        public C <>4__this;

        private TaskAwaiter <>u__1;

        private void MoveNext()
        {
            int num = <>1__state;
            try
            {
                TaskAwaiter awaiter;
                if (num != 0)
                {
                    awaiter = Task.Delay(3000).GetAwaiter();
                    if (!awaiter.IsCompleted)
                    {
                        num = (<>1__state = 0);
                        <>u__1 = awaiter;
                        <Foo>d__1 stateMachine = this;
                        <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
                        return;
                    }
                }
                else
                {
                    awaiter = <>u__1;
                    <>u__1 = default(TaskAwaiter);
                    num = (<>1__state = -1);
                }
                awaiter.GetResult();
            }
            catch (Exception exception)
            {
                <>1__state = -2;
                <>t__builder.SetException(exception);
                return;
            }
            <>1__state = -2;
            <>t__builder.SetResult();
        }

        void IAsyncStateMachine.MoveNext()
        {
            //ILSpy generated this explicit interface implementation from .override directive in MoveNext
            this.MoveNext();
        }

        [DebuggerHidden]
        private void SetStateMachine([Nullable(1)] IAsyncStateMachine stateMachine)
        {
        }

        void IAsyncStateMachine.SetStateMachine([Nullable(1)] IAsyncStateMachine stateMachine)
        {
            //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
            this.SetStateMachine(stateMachine);
        }
    }

    public void M()
    {
    }

    [NullableContext(1)]
    [AsyncStateMachine(typeof(<Foo>d__1))]
    [DebuggerStepThrough]
    public Task Foo()
    {
        <Foo>d__1 stateMachine = new <Foo>d__1();
        stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
        stateMachine.<>4__this = this;
        stateMachine.<>1__state = -1;
        stateMachine.<>t__builder.Start(ref stateMachine);
        return stateMachine.<>t__builder.Task;
    }
}
View Code

同步上下文

1.使用Synchronization同步上下文切换UI线程

2.TaskScheduler

常见误区

资料

https://www.bilibili.com/video/BV1yB4y1R7tc/?spm_id_from=333.788&vd_source=a56db24cb8cab4dd8153f9a519787c89

https://github.com/BYJRK/DotNet-Discussions/discussions/154

.NET中的异步编程

https://www.cnblogs.com/Vincent-yuan/p/13417356.html

https://www.cnblogs.com/shanzhiming/p/12439214.html

.NET 异步,你也许不知道的5种用法

http://www.cnblogs.com/x-xk/archive/2013/06/05/3118005.html

http://www.cnblogs.com/tdws/p/5679001.html

http://www.cnblogs.com/liqingwen/p/5831951.html

http://www.cnblogs.com/liqingwen/p/5831951.html

posted @ 2021-11-21 13:43  ~沐风  阅读(568)  评论(0编辑  收藏  举报