網(wǎng)站首頁 編程語言 正文
我們知道,每個(gè)應(yīng)用程序就是一個(gè)進(jìn)程,一個(gè)進(jìn)程有多個(gè)線程。Task Parallel Library為我們的異步編程、多線程編程提供了強(qiáng)有力的支持,它允許一個(gè)主線程運(yùn)行的同時(shí),另外的一些線程或Task也同時(shí)運(yùn)行。本篇體驗(yàn)基本用法。
基本用法
Taks的構(gòu)造函數(shù)接收的類型是Action,也就是一個(gè)委托。
static void Main(string[] args)
{
var t1 = new Task(() =>
{
Console.WriteLine("任務(wù)1開始");
Thread.Sleep(1000);
Console.WriteLine("任務(wù)1結(jié)束");
});
t1.Start();
Console.ReadKey();
}
如果把方法放到外面。
static void Main(string[] args)
{
var t1 = new Task(() => DoSth(1,2000));
t1.Start();
Console.ReadKey();
}
static void DoSth(int id, int sleepTime)
{
Console.WriteLine("任務(wù){(diào)0}開始",id);
Thread.Sleep(sleepTime);
Console.WriteLine("任務(wù){(diào)0}結(jié)束",id);
}
如果有多個(gè)Task同時(shí)執(zhí)行。
static void Main(string[] args)
{
var t1 = new Task(() => DoSth(1,2000));
t1.Start();
var t2 = new Task(() => DoSth(2, 1500));
t2.Start();
var t3 = new Task(() => DoSth(3, 3000));
t3.Start();
Console.ReadKey();
}
如果有很多Task,每個(gè)Task手動(dòng)啟動(dòng)的話很費(fèi)事,Task Parallel Library為我們準(zhǔn)備了Task工廠。
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() => DoSth(1, 2000));
var t2 = Task.Factory.StartNew(() => DoSth(2, 1500));
var t3 = Task.Factory.StartNew(() => DoSth(3, 3000));
Console.ReadKey();
}
如果我們想在一個(gè)任務(wù)結(jié)束之后立即執(zhí)行某個(gè)任務(wù),可以使用ContinueWith方法。
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)).ContinueWith((pre)=> DoOtherThing(4,2000));
var t2 = Task.Factory.StartNew(() => DoSth(2, 1500));
var t3 = Task.Factory.StartNew(() => DoSth(3, 3000));
Console.ReadKey();
}
static void DoSth(int id, int sleepTime)
{
Console.WriteLine("任務(wù){(diào)0}開始",id);
Thread.Sleep(sleepTime);
Console.WriteLine("任務(wù){(diào)0}結(jié)束",id);
}
static void DoOtherThing(int id, int sleepTime)
{
Console.WriteLine("其他任務(wù){(diào)0}開始", id);
Thread.Sleep(sleepTime);
Console.WriteLine("其他任務(wù){(diào)0}結(jié)束", id);
}
如果希望等待所有的Task執(zhí)行完畢,使用WaitAll方法。
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() => DoSth(1, 2000));
var t2 = Task.Factory.StartNew(() => DoSth(2, 1500));
var t3 = Task.Factory.StartNew(() => DoSth(3, 3000));
var taskList = new List<Task> {t1, t2, t3};
Task.WaitAll(taskList.ToArray());
Console.WriteLine("我是在所有Task執(zhí)行完畢后才執(zhí)行的");
Console.ReadKey();
}
如果想手動(dòng)取消結(jié)束某個(gè)Task,需要為方法帶上CancellationToken類型參數(shù)。
static void Main(string[] args)
{
var source = new CancellationTokenSource();
try
{
var t1 =
Task.Factory.StartNew(() => DoSth(1, 1000, source.Token))
.ContinueWith((pre) => DoOtherThing(2, 2000));
source.Cancel();
}
catch (Exception ex)
{
Console.WriteLine(ex.GetType());
}
Console.WriteLine("haha");
Console.ReadKey();
}
static void DoSth(int id, int sleepTime, CancellationToken token)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("任務(wù)被取消");
token.ThrowIfCancellationRequested();
}
Console.WriteLine("任務(wù){(diào)0}開始",id);
Thread.Sleep(sleepTime);
Console.WriteLine("任務(wù){(diào)0}結(jié)束",id);
}
static void DoOtherThing(int id, int sleepTime)
{
Console.WriteLine("其他任務(wù){(diào)0}開始", id);
Thread.Sleep(sleepTime);
Console.WriteLine("其他任務(wù){(diào)0}結(jié)束", id);
}
如何從Task從獲取方法的返回結(jié)果呢?
static void Main(string[] args)
{
Console.WriteLine("開始計(jì)算");
Task<int> t = Task.Factory.StartNew(() => Sum(1, 2));
Console.WriteLine("等待結(jié)果");
Console.WriteLine(t.Result);
Console.ReadKey();
}
static int Sum(int a, int b)
{
return a + b;
}
后面一個(gè)Task獲取前面一個(gè)Task的返回值。
static void Main(string[] args)
{
Task<string> firstTask = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("第一個(gè)任務(wù)開始");
return "hi from the one";
});
Task secondTask = firstTask.ContinueWith((prevoursTask) =>
{
Console.WriteLine("這里是第二個(gè)任務(wù),獲取到第一個(gè)任務(wù)的返回值是{0}",prevoursTask.Result,TaskContinuationOptions.OnlyOnRanToCompletion);
});
secondTask.Wait();
Console.ReadKey();
}
等待所有Task完成。
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() =>
{
Console.WriteLine("第一個(gè)任務(wù)");
Thread.Sleep(1000);
});
var t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("第二個(gè)任務(wù)");
Thread.Sleep(1000);
});
var taskList = new List<Task> {t1, t2};
Task.Factory.ContinueWhenAll(taskList.ToArray(), (t) => { Console.WriteLine("所有任務(wù)完成我就出來"); });
Console.ReadKey();
}
如果是嵌套Task。
static void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
Task child = Task.Factory.StartNew(() =>
{
Console.WriteLine("我是子任務(wù)");
}, TaskCreationOptions.AttachedToParent);
}).Wait();
Console.ReadKey();
}
啟動(dòng)Task的幾種方式
1、通過Task.Factory.StartNew方法。
static void Main(string[] args)
{
Task.Factory.StartNew(() => SaySth("hello"));
Console.ReadKey();
}
static void SaySth(string msg)
{
Console.WriteLine(msg);
}
2、通過Task的Start實(shí)例方法
static void Main(string[] args)
{
var t = new Task(() => SaySth("hello"));
t.Start();
Console.ReadKey();
}
或者干脆用委托。
static void Main(string[] args)
{
Task t = new Task(delegate {SaySth("hello");});
t.Start();
Console.ReadKey();
}
3、Task的靜態(tài)方法Run
static void Main(string[] args)
{
Task t = Task.Run(() => SaySth("hello"));
Console.ReadKey();
}
static void SaySth(string msg)
{
Console.WriteLine(msg);
}
一個(gè)例子
比如說要下載某個(gè)頁面,在保持當(dāng)前UI界面無影響的情況下,使用Task在后臺(tái)啟動(dòng)任務(wù)下載某個(gè)頁面。
static void Main(string[] args)
{
Console.WriteLine("界面內(nèi)容");
Task<string> r = DownloadAsync("http://www.baidu.com");
while (!r.IsCompleted)
{
Console.Write(".");
Thread.Sleep(250);
}
Console.WriteLine(r.Result);
Console.ReadKey();
}
private static string DownloadWebPage(string url)
{
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
private static Task<string> DownloadAsync(string url)
{
return Task.Factory.StartNew(() => DownloadWebPage(url));
}
原文鏈接:https://www.cnblogs.com/darrenji/p/4436411.html
相關(guān)推薦
- 2022-08-15 Python自制隨機(jī)數(shù)生成算法
- 2022-04-03 C#中的char與string詳解_C#教程
- 2023-05-12 oracle刪除數(shù)據(jù)但表空間占用率沒有減小的情況_oracle
- 2022-08-27 C++中Boost的智能指針weak_ptr_C 語言
- 2022-05-22 C#中深拷貝和淺拷貝的介紹與用法_C#教程
- 2022-05-05 Python實(shí)現(xiàn)蟻群算法_python
- 2023-01-11 C++入門教程之引用與指針_C 語言
- 2022-11-21 Android性能優(yōu)化之JVMTI與內(nèi)存分配_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支