siso

明天会更好!

C# async await 学习笔记2

C# async await 学习笔记1(http://www.cnblogs.com/siso/p/3691059.html)

 提到了ThreadId是一样的,突然想到在WinForm中,非UI线程是无法直接更新UI线程上的控件的问题。

于是做了如下测试:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Task<string> LongTimeTask()
        {
            tbResult.Text += "LongTimeTask开始:" + DateTime.Now.ToString() + "\r\n";             

            Task<string> task = new Task<string>(() => { Thread.Sleep(5000); return "这是任务返回值"; });
            task.Start();
        
            tbResult.Text += "LongTimeTask结束:" + DateTime.Now.ToString() + "\r\n";    

            return task;
        }

        async void AsyncCall()
        {
            tbResult.Text += "AsyncCall开始:" + DateTime.Now.ToString() + "\r\n";     
            string result = await LongTimeTask(); //await调用的方法需要返回Task或Task<T>,且调用await所在的方法要有async关键字
            tbResult.Text += "AsyncCall:" + result + "\r\n"; 
            tbResult.Text += "AsyncCall结束:" + DateTime.Now.ToString() + "\r\n"; 
        }   

        private void button1_Click(object sender, EventArgs e)
        {
            tbResult.Text += "Main开始:" + DateTime.Now.ToString() + "\r\n";
            AsyncCall();
            tbResult.Text += "Main结束:" + DateTime.Now.ToString() + "\r\n";
        }
    }
}

 发现,在AsyncCall中,可以直接访问TextBox(tbResult),如果对上面的测试觉得没什么奇怪,大家可以先看下面的代码。

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        void LongTimeTask()
        {
            Thread.Sleep(5000);
          
            tbResult.Text += "AsyncCall结束:" + DateTime.Now.ToString() + "\r\n";
        } 

        private void button1_Click(object sender, EventArgs e)
        {
            tbResult.Text += "Main开始:" + DateTime.Now.ToString() + "\r\n";

            Thread t = new Thread(LongTimeTask);
            t.Start();

            tbResult.Text += "Main结束:" + DateTime.Now.ToString() + "\r\n";
        }
    }
}

运行到 LongTimeTask的tbResult.Text时,提示:线程间操作无效: 从不是创建控件“tbResult”的线程访问它。

      为了能在非UI线程中访问到UI线程中的控件,于是需作如下修改:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        delegate void UpdateUIDelegate();
        UpdateUIDelegate updateUIDelegate;        

        public Form2()
        {
            InitializeComponent();
            updateUIDelegate = new UpdateUIDelegate(UpdateUI);
        }

        void UpdateUI()
        {
            if (tbResult.InvokeRequired)
            {
                tbResult.Invoke(updateUIDelegate);
            }
            else
            {
                tbResult.Text += "AsyncCall结束:" + DateTime.Now.ToString() + "\r\n";
            }
        }

        void LongTimeTask()
        {
            Thread.Sleep(5000);
            UpdateUI();        
        } 

        private void button1_Click(object sender, EventArgs e)
        {
            tbResult.Text += "Main开始:" + DateTime.Now.ToString() + "\r\n";

            Thread t = new Thread(LongTimeTask);
            t.Start();

            tbResult.Text += "Main结束:" + DateTime.Now.ToString() + "\r\n";
        }
    }
}

 

posted on 2014-04-26 14:44  siso  阅读(370)  评论(0编辑  收藏  举报

导航