C# Task(任务调度)

参考:https://www.cnblogs.com/zhaoshujie/p/11082753.html

一个Task表示一个异步操作,Task的创建和执行都是独立的,因此可以对关联操作的执行拥有完全的控制权。

一:Task的优势
1: Task支持线程的取消、完成、失败通知等交互性操作
2: Task支持线程执行的先后次序

 

Task t = new Task(() =>
{
    
});
t.ContinueWith((task) =>
{
    
});
t.Start();

  

二:Task的完成状态
任务Task有这样一些属性,让我们查询任务完成时的状态:
1: IsCanceled,因为被取消而完成
2: IsCompleted,成功完成
3: IsFaulted,因为发生异常而完成

CancellationTokenSource cts = new CancellationTokenSource();
Task<int> t = new Task<int>(() => Add(cts.Token), cts.Token);
t.Start();
t.ContinueWith(TaskEnded);
//等待按下任意一个键取消任务
Console.ReadKey();
cts.Cancel();

  

任务Task创建方式

方式一、new Task 无返回值

Task task = new Task(() =>{});
task.Start();

  

new Task 有返回值的方式,Task 与 ContinueWith

//先执行Task
Task<int> task = new Task<int>(() => { 
    return 0; 
});
//其次执行ContinueWith
task.ContinueWith(t =>
{
    int result = t.Result;
});
task.Start();

   

方式二、使用 TaskMethod 无返回值

Task task = new Task(() => TaskMethod("Task 2"));
task.Start();

    

方式三、Task.Run

Task task = Task.Run(() => TaskMethod("Task 3"));

    

方式四、直接异步的方法

Task.Factory.StartNew(() => TaskMethod("Task 3"));

方式五、异步

Task.Run(async () =>
{
    await Task.Factory.StartNew(() =>
    {
                        
    });
});

  

Task任务并行

List<Task> taskList = new List<Task>();
taskList.Add(Task.Run(() =>
{

}));
taskList.Add(Task.Run(() =>
{

}));
taskList.Add(Task.Run(() =>
{

}));

    

//主线程阻塞,等待结束
Task.WaitAll(taskList.ToArray());
主线程 Code ....执行

方式三、异步非阻塞

Task[] tlist = new Task[] { 
    Task.Factory.StartNew(() => { 
        Thread.Sleep(3000); 
    }), 
    Task.Factory.StartNew(() => {
        Thread.Sleep(90000);
    }) 
};
Task.WhenAny(tlist).ContinueWith((s) => {
    return s;
});

    

使用IProgress实现异步编程的进程通知

private void btnSub_Click(object sender, RoutedEventArgs e)
{
    Task task = Display();
}
void DoProcessing(IProgress<int> progress)
{
    if (progress != null)
    {
        progress.Report(1);
    }
}

async Task Display()
{
    //当前线程
    var progress = new Progress<int>(percent =>
    {
        this.Title = percent.ToString();
    });
    //线程池线程
    await Task.Run(() => DoProcessing(progress));
}

  

本文来源参考:https://www.cnblogs.com/zhaoshujie/p/11082753.html 

什么是并行
并行是指两个或者多个事件在同一时刻发生
在程序运行中,并行指多个CPU核心同时执行不同的任务;对于单核心CPU,严格来说是没有程序并行的。并行是为了提高任务执行效率,更快的获取结果。

与并发的区别
并发是指两个或者多个事件在同一时段发生。
相对于并行,并发强调的是同一时段,是宏观上的同时发生。实际上,同一时刻只有一个任务在被执行,多个任务是分时地交替执行的。并发是为了更合理地分配资源。

实现并行,我们要借助进程和线程。
进程是正在运行的程序的实例。
线程被包含在进程之中,是进程中的实际运作单位。

前台线程和后台线程
.NET把线程分为前台线程和后台线程,两者几乎相同,唯一的区别是,前台线程会阻止进程的正常退出,后台线程则不会。

线程池 ThreadPool
线程的创建和销毁要耗费很多时间,而且过多的线程不仅会浪费内存空间,还会导致线程上下文切换频繁,影响程序性能。为改善这些问题,.NET运行时(CLR)会为每个进程开辟一个全局唯一的线程池来管理其线程。

多线程
1、在执行一个较长时间的任务时,不能阻塞UI界面响应,必须通过后台线程处理;
2、在执行批量计算密集型任务时,采用多线程技术可以提高运行效率;

传统使用的多线程技术有:
Thread & ThreadPool
Timer
BackgroundWorker

Task内部也是对ThreadPool的封装

采用并行编程方法:
Parallel.For(1, 10000, x=>
{
bool b = IsPrimeNumber(x);
Console.WriteLine($"{i}:{b}");
});
//使用并行循环处理数据更新
List<string> lists = new List<string>();
System.Threading.Tasks.Parallel.For(0, lists.Count, (int i) =>
{
string sql = string.Format("update table1 set IsExit =1 where Id='{0}'", lists[i]);
Execute(sql);
});

和Task类似,Parallel类仍然是对ThreadPool的封装。

需要通知一个任务结束,或一个任务等待某个条件进入下一个状态,这就需要用到任务同步的技术。
采用WaitOne来等待

异步编程模型(await、async)

非UI线程不能访问UI控件,可以使用Invoke

多线程环境下的数据安全
private static ConcurrentDictionary<int, string> Dic = new ConcurrentDictionary<int, string>();
//添加操作
Dic.TryAdd(i, i.ToString());

多线程的异常处理
基本原则:不要轻易捕获根异常;
多线程的内部异常不会传播到主线程,应该在内部进行处理,可以通过事件推到主线程来;
应用程序层面可以捕获根异常,做一些记录工作,切不可隐匿异常。
将异常包装成事件推送到主线程,交给主线程处理。
参考:https://www.cnblogs.com/seabluescn/p/12973936.html

异步编程中,线程之间只要互不影响,考虑同步问题即可。而在并行编程中,则要求多个线程在同一时刻同时运行。

posted @ 2021-06-07 17:09  microsoft-zhcn  阅读(5467)  评论(0编辑  收藏  举报