zl程序教程

您现在的位置是:首页 >  前端

当前栏目

async await与async await Task.Run

async Task run await
2023-09-11 14:14:05 时间

 

普通的async await方法其实是一个同步的异步调用,此方式并不开启新的线程,只是一个多任务处理模式,只是主线程在运行时不会阻塞卡死。此方式只能调用异步方法。

(使用async和await定义异步方法不会创建新线程,所以使用Thread.Sleep(3000)主线程也会阻塞卡死)

(由于不是开始新线程,所以在方法内页面的所有控件都可以直接访问)

而async await Task.Run是一个真实的异步模式,此方式实质就是开启一个新的托管的线程。并且此方式可以调用同步方法。

(使用await Task.Run定义异步方法会创建新线程,所以使用Thread.Sleep(3000)不影响主线程)

(不考虑资源消耗的情况下,使用await Task.Run貌似是个更好的选择)(当然开启新线程会消耗更多的资源)

(由于是开启新新线程,所以在await Task.Run方法体中就不可以直接调用页面内控件了,需要使用this.Dispatcher.BeginInvoke调用控件)

 

task.run 看来就是以前的开一个线程,类似于thread.start
不是必要与await一起使用的
可以单独使用
加await就是相当于异步同步操作
task才是核心
await和async都是怎么调用的定义

 

关于线程中更新控件值原则: 如果线程里执行的程序如果一直要更新控件值,那么线程中需要调用控件并且修改值(比如进度条),如果控件只需要线程运行完成后的结果值,那么不应该在线程中调用控件,只需要在线程结束后获取的值在线程外主线程直接更新控件值就可以了(当然也不是绝对,比如更新的数据量大,那么还是可能造成主线程阻塞,此时在线程内部更新控件值也是个好选择)

lamada表达式 这种 省了一个委托和传参

 

    public partial class YiBuTest : Window
    {
        public YiBuTest()
        {
            InitializeComponent();
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {

        }


        private async void btnClick_Click(object sender, EventArgs e)
        {
            // 这里可以做一些不依赖回复的操作
            richTextBox1.Text += "\r\n等待服务器回复中.................\n";

            //long length = await AccessWebAsync();
            long length = await GetAwaitRunString("参数");

            richTextBox1.Text += String.Format("\n 回复成功,字节长度为:  {0}.\r\n", length);

            txbMainThreadID.Text = Thread.CurrentThread.ManagedThreadId.ToString();
        }

        #region await调用异步方法(使用async和await定义异步方法不会创建新线程,所以使用Thread.Sleep(3000)主线程也会阻塞卡死)(由于不是开始新线程,所以在方法内页面的所有控件都可以直接访问)
        // 使用C# 5.0中提供的async 和await关键字来定义异步方法
        // 从代码中可以看出C#5.0 中定义异步方法就像定义同步方法一样简单。
        // 使用async和await定义异步方法不会创建新线程,
        // 它运行在现有线程上执行多个任务.
        // 此时不知道大家有没有一个疑问的?在现有线程上(即UI线程上)运行一个耗时的操作时,
        // 为什么不会堵塞UI线程的呢?
        // 这个问题的答案就是 当编译器看到await关键字时,线程会
        private async Task<long> AccessWebAsync()
        {
            MemoryStream content = new MemoryStream();

            // 对MSDN发起一个Web请求
            HttpWebRequest webRequest = WebRequest.Create("https://docs.microsoft.com/zh-cn/") as HttpWebRequest;
            if (webRequest != null)
            {
                // 返回回复结果
                using (WebResponse response = await webRequest.GetResponseAsync())
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        await responseStream.CopyToAsync(content);
                    }
                }
            }

            txbAsynMethodID.Text = Thread.CurrentThread.ManagedThreadId.ToString();

            return content.Length;
        }
        #endregion

        #region await调用同步方法await Task.Run(使用await Task.Run定义异步方法会创建新线程,所以使用Thread.Sleep(3000)不影响主线程)(不考虑资源消耗的情况下,使用await Task.Run貌似是个更好的选择)(当然开启新线程会消耗更多的资源)
        //(由于是开启新新线程,所以在await Task.Run方法体中就不可以直接调用页面内控件了)
        private async Task<long> GetAwaitRunString(string str)
        {

            var task = await Task.Run<long>(() =>
            {

                return tongbufangfa(str);

            });

            return task;
        }

        private long tongbufangfa(string str)
        {
            //线程停顿3秒    
            Thread.Sleep(3000);
            MemoryStream content = new MemoryStream();

            // 对MSDN发起一个Web请求
            HttpWebRequest webRequest = WebRequest.Create("https://docs.microsoft.com/zh-cn/") as HttpWebRequest;
            if (webRequest != null)
            {
                // 返回回复结果
                using (WebResponse response = webRequest.GetResponse())
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        responseStream.CopyTo(content);
                    }
                }
            }

            return content.Length;
        }
        #endregion
    }