C#开发中关于Task后台进程的解读

demo

代码地址:https://gitee.com/chenheze90/L23_TaskAndThread
demo下载:https://gitee.com/chenheze90/L23_TaskAndThread/repository/archive/master.zip

前言

基本上,C#软件开发都会涉及线程的开发。线程是一个非常好的工具,C#早期用的最多的是Thread,现在建议大家用Task。本文主要介绍Task的功能。

async是否后台线程

理论上,是的,async方法就是后台线程。首先我们以正常代码为例,如下代码测试所示

static void Main(string[] args)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("当前线程的ID是:" + threadId);
            TestthreadId();
            Console.ReadLine();
        }

        private static void TestthreadId()
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("方法中的线程的ID是:" + threadId);
        }

在Main方法中执行一个正常的方法,我们可以看到两个的线程id是一致的
在这里插入图片描述
如果仅仅是在方法前增加async修饰,则会被当做同步方法来使用
在这里插入图片描述
运行的结果和第一份代码一致
在这里插入图片描述
但是如果加了异步方法,如 await Task.Delay(1000),则此方法就会变成异步方法,且线程id也会改变,如下代码所示

private static async void TestthreadId()
        {
            await Task.Delay(1000);
            int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("方法中的线程的ID是:" + threadId);
        }

在这里插入图片描述
Main方法主线程的线程ID是1,而async方法的线程ID是4
以上实验证明,async修饰的方法是异步方法

async不为后台线程的特殊情况——winform、wpf

特殊:在wpf和winform中,async不是后台线程
我们先用Thread做个示范

public Form1()
        {
            InitializeComponent();
        }
        int i = 0;
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread t = new Thread(AddNum);
            t.Start();
        }

        private void AddNum()
        {
            while (true)
            {
                // 一定要用异步方法!!!!不然会报错
                Invoke(new Action(() =>
                {
                    textBox1.Text = (++i).ToString();
                }));
                Thread.Sleep(500);
            }
        }

在这里,我们用thread做了个线程,不断增加文本框的数字
在这里插入图片描述
用thread做线程,一切正常
我们接下来,我们把thread改成async方法,如下代码所示

int i = 0;
        private void Form1_Load(object sender, EventArgs e)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("当前线程的ID是:" + threadId);
            AddNum();
        }

        private async void AddNum()
        {
            await Task.Delay(3000);
            int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("方法中的线程的ID是:" + threadId);
            while (true)
            {
            	// 即使没有用Invoke方法,也能够操作UI控件,说明方法和主线程在同一个线程中,输出的线程ID也能证明这一点
                textBox1.Text = (++i).ToString();
                await Task.Delay(500);
            }
        }

可以看到,async中没有用Invoke
针对winform和wpf,在async方法中,即使没有用Invoke方法,也能够操作UI控件
这个是他特殊的地方

Task.Run到底有没有在异线程运行

有的,Task.Run确实在异步线程运行,代码如下

int i = 0;
        private void Form1_Load(object sender, EventArgs e)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("当前线程的ID是:" + threadId);
            Task.Run(() =>
            {
                Console.WriteLine("方法2中的线程的ID是:" + Thread.CurrentThread.ManagedThreadId);
                // 一定要用异步方法!!!!
                Invoke(new Action(() =>
                {
                    textBox1.Text = "Task.Run测试";
                }));
            });
        }

在这里插入图片描述
在输出界面,我们可以看到输出内容。Task.Run确实在异步线程运行

当前线程的ID是:1
方法2中的线程的ID是:4

后台线程控制前端UI的方法集锦

winform

this.Invoke((Action)(() => // this是WinForms窗体,或者其他任何控件都可以
{
// 在主线程中执行需要操作的UI代码
}));

this.BeginInvoke((Action)(() => // this是WinForms窗体,或者其他任何控件都可以
{
// 在主线程中执行需要操作的UI代码
}));

wpf

Application.Current.Dispatcher.Invoke(((Action)delegate ()
{
// 在主线程中执行需要操作的UI代码
}));

await Application.Current.Dispatcher.BeginInvoke(((Action)delegate ()
{
// 在主线程中执行需要操作的UI代码
}));

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值