异步编程学习

 

摘抄自文章:.NET中的异步编程

异步编程中重要的技术点在于:

1)当异步线程在工作完成时,如何通知调用线程?

2)当异步线程出现异常的时,该如何处理?

3)异步线程工作的进度,如何实时的通知调用线程?

4)如何在调用线程中,取消正在工作的异步线程,并进行回滚操作?

 

完整的异步调用例子:

class Program
    {
        public delegate int DoWord(int count);
        static void Main(string[] args)
        {
            DoWord d = new DoWord(WorkPro);
            IAsyncResult r= d.BeginInvoke(100,CallBack ,d);//no.1
            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(10);//主线程需要做的事
            }
            Console.WriteLine("主线程done");
            Console.ReadKey();
        }
        public static int WorkPro(int count)
        {
            int sum = 0;
            //做一些耗时的工作
            for (int i = 0; i < count; i++)
            {
                sum += i;
                Thread.Sleep(10);
            }
            return sum;        
        }
 
        public static void CallBack(IAsyncResult r)
        {
            DoWord d = (DoWord)r.AsyncState;
            Console.WriteLine("异步调用完成,返回结果为{0}", d.EndInvoke(r));
        }
    }

以上被博主称之为异步函数模型。

 

Thread类

class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(WorkPro);//no.1
            t.IsBackground = true;//no.2
            t.Start(1000);//no.3
        }
        public static void WorkPro(object  t)
        {
            //做一些耗时的工作   
            int count=(int)t;
            for (int i = 0; i < count; i++)
            {
                Thread.Sleep(2000);
            }
 
            Console.WriteLine("任务处理完成");
        }
    }
Thread类的使用虽然简单,但是它还是有一定的劣势的,一般不推荐使用。
1)Thread类创建的是一个专用线程,建立一个专用线程是非常耗用系统的资源,建议是使用线程池中的线程。
2)Thread类不能很好的和调用线程进行交互,当任务完成时不能及时的通知,在调用线程也不能随时的取消正在进行的任务。
另外在以下情况下,就只能选择使用Thread类了。
1)执行任务的线程要以非普通的优先级去执行,因为线程池的线程都是以普通优先级运行的。
2)执行任务的线程要表现为一个前台线程,因为线程池的线程始终都是一个后台线程。
3)异步执行的任务需要长时间的,那么就可以使用Thread类为该任务建立一个专用线程。

 

Task类

public partial class Form1 : Form
    {
        private readonly TaskScheduler contextTaskScheduler;//声明一个任务调度器
        public Form1()
        {
            InitializeComponent();
            contextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();//no.1获得一个上下文任务调度器
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Task<int> t = new Task<int>((n) => Sum((int)n),100);
            t.Start();
            t.ContinueWith(task =>this.textBox1 .Text =task.Result.ToString(),contextTaskScheduler);//当任务执行完之后执行
            t.ContinueWith(task=>MessageBox .Show ("任务出现异常"),CancellationToken.None ,TaskContinuationOptions.OnlyOnFaulted,contextTaskScheduler );//当任务出现异常时才执行
        }
        int Sum(int count)
        {
            int sum = 0;
            for (int i = 0; i < count; i++)
            {
                Thread.Sleep(10);
                sum += i;
            }
            Console.WriteLine("任务处理完成");
            return sum;
        }
    }

这是一个比较完整的Task应用例子。详情可以阅读摘抄的博客原文。

 

博客:Winform实现多线程异步更新UI(进度及状态信息)

有个完整的使用多线程的例子。代码比较复杂。

 

 ------------------------------

20190907更新

文章:C#异步的世界【上】

写了早期C#中实现异步的方法。

 文章:C#异步的世界【下】

和上篇配合看

 

 

 

 

 
 

 

posted on 2018-11-13 11:01  荆棘人  阅读(118)  评论(0编辑  收藏  举报

导航