国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C# 線程--第四線程實(shí)例

2019-11-17 02:32:28
字體:
供稿:網(wǎng)友

C# 線程--第四線程實(shí)例

概述

在前面幾節(jié)中和大家分享了線程的一些基礎(chǔ)使用方法,本章結(jié)合之前的分享來編寫一些日常開發(fā)中應(yīng)用實(shí)例,和編寫多線程時(shí)一些注意點(diǎn)。如大家有好的實(shí)例也歡迎分享..

應(yīng)用實(shí)例

應(yīng)用:定時(shí)任務(wù)程序

場景:系統(tǒng)中常常會有一些需要定時(shí)去循環(huán)執(zhí)行的存儲過程或方法等,這時(shí)就出現(xiàn)了定時(shí)任務(wù)小程序。

模型:查詢需定時(shí)執(zhí)行的計(jì)劃任務(wù)-->插入線程池-->執(zhí)行任務(wù)

static void MainMethod(){    Thread thead;    thead = new Thread(QueryTask);    thead.IsBackground = true;    thead.Start();    Console.Read();}/// <summary>/// 查詢計(jì)劃任務(wù)/// </summary>static void QueryTask(){    TaskModel todo_taskModel;    while (true)    {        int count = new Random().Next(1, 10);    //模擬產(chǎn)生任務(wù)記錄數(shù)        for (int i = 0; i < count; i++)        {            todo_taskModel = new TaskModel() { TaskID = i, ITime = DateTime.Now };            ThreadPool.QueueUserWorkItem(InvokeThreadMethod, todo_taskModel);        }        Thread.Sleep(30000);    //30s循環(huán)一次    }}/// <summary>/// 完成計(jì)劃任務(wù)/// </summary>/// <param name="taskModel"></param>static void InvokeThreadMethod(object taskModel){    TaskModel model = (TaskModel)taskModel;    Console.WriteLine("執(zhí)行任務(wù)ID:{0}......執(zhí)行完成.{1}", model.TaskID, model.ITime);}/// <summary>/// 任務(wù)實(shí)體/// </summary>class TaskModel{    public int TaskID { get; set; }    public DateTime ITime { get; set; }}

1.查詢計(jì)劃任務(wù)時(shí)只管有任務(wù)就推給線程池,不等待線程池中任務(wù)是否完成.(避免有些計(jì)劃任務(wù)耗時(shí)比較長,阻塞后面定時(shí)任務(wù)執(zhí)行時(shí)間)每隔30秒循環(huán)一次計(jì)劃任務(wù).

2.每條計(jì)劃任務(wù)完成后打印相應(yīng)信息.(也可記錄日志)

3.如果查詢計(jì)劃任務(wù)記錄數(shù)較多,可調(diào)整相應(yīng)的循環(huán)時(shí)間間隔。避免任務(wù)插入線程池時(shí)間過長阻塞后面定時(shí)任務(wù)執(zhí)行時(shí)間。

應(yīng)用:數(shù)據(jù)推送程序

場景:在我們?nèi)粘O到y(tǒng)中會存在很多接口數(shù)據(jù)需要實(shí)時(shí)推送給第三方平臺(如:會員信息發(fā)生變化推送給微信平臺..)。這時(shí)我們就需寫一些數(shù)據(jù)推送程序。

模型:檢索任務(wù)-->插入線程池-->等待線程池任務(wù)完成-->提示任務(wù)完成

static void MainMethodB(){    Thread thread = new Thread(QueryTaskB);    thread.IsBackground = true;    thread.Start();    Console.Read();}static void QueryTaskB(){    MutipleThreadResetEvent countdown;    TaskModeB model;    while (true)    {        int RandomNumber = new Random().Next(100, 200);        countdown = new MutipleThreadResetEvent(RandomNumber);        for (int i = 0; i < RandomNumber; i++)        {            model = new TaskModeB() { TaskId = i, ITime = DateTime.Now, manualResetEvent = countdown };            ThreadPool.QueueUserWorkItem(InvokeThreadMethodB, model);        }        //等待所有線程執(zhí)行完畢        countdown.WaitAll();        Console.WriteLine("線程池任務(wù)已完成.完成時(shí)間:{0}", DateTime.Now);        Thread.Sleep(30000);    }}static void InvokeThreadMethodB(object obj){    TaskModeB model = (TaskModeB)obj;    Thread.Sleep(1000);    Console.WriteLine("執(zhí)行任務(wù)ID:{0},執(zhí)行時(shí)間:{1},完成時(shí)間:{2}", model.TaskId, model.ITime, DateTime.Now);    //發(fā)送信號量 本線程執(zhí)行完畢    model.manualResetEvent.SetOne();}class TaskModeB{    public int TaskId { set; get; }    public DateTime ITime { set; get; }    public MutipleThreadResetEvent manualResetEvent { set; get; }}/// <summary>/// 解決問題:WaitHandle.WaitAll(evetlist)方法最大只能等待64個ManualResetEvent事件/// </summary>public class MutipleThreadResetEvent{    PRivate readonly ManualResetEvent done;    private readonly int total;    private long current;    /// <summary>    /// 構(gòu)造函數(shù)    /// </summary>    /// <param name="total">需要等待執(zhí)行的線程總數(shù)</param>    public MutipleThreadResetEvent(int total)    {        this.total = total;        current = total;        done = new ManualResetEvent(false);    }    /// <summary>    /// 喚醒一個等待的線程    /// </summary>    public void SetOne()    {        // Interlocked 原子操作類 ,此處將計(jì)數(shù)器減1        if (Interlocked.Decrement(ref current) == 0)        {            //當(dāng)所以等待線程執(zhí)行完畢時(shí),喚醒等待的線程            done.Set();        }    }    /// <summary>    /// 等待所以線程執(zhí)行完畢    /// </summary>    public void WaitAll()    {        done.WaitOne();    }    /// <summary>    /// 釋放對象占用的空間    /// </summary>    public void Dispose()    {        ((IDisposable)done).Dispose();    }}

QueryTaskB()在檢索任務(wù)記錄數(shù)后會記錄任務(wù)條數(shù),并實(shí)例化對應(yīng)的ManualResetEvent數(shù)組,做為參數(shù)傳給線程池中線程任務(wù)。

最后等待線程池中所有任務(wù)執(zhí)行完成。后續(xù)可根據(jù)實(shí)際需要編寫各自業(yè)務(wù)邏輯。

兩個實(shí)例的不同點(diǎn):是否等待線程池中的所有任務(wù)完成。

實(shí)例1中定時(shí)任務(wù)對執(zhí)行的時(shí)間要求比較高,到了某個時(shí)間點(diǎn)必須執(zhí)行某個任務(wù)。所以不能等待線程池中的任務(wù)完成。

缺點(diǎn):有任務(wù)就插入線程池,有些任務(wù)可能會執(zhí)行很久,線程池每隔30秒循環(huán)一次,最后會導(dǎo)致線程池中有存在很多耗時(shí)很長的任務(wù)在線程池中未執(zhí)行完。當(dāng)線程池中線程數(shù)達(dá)到1023(線程池默認(rèn)最大線程數(shù))后線程池就不會在創(chuàng)建新的線程數(shù)去完成新的任務(wù),只能等待當(dāng)前線程池中線程數(shù)得到釋放。

實(shí)例2中數(shù)據(jù)推送程序?qū)ν扑偷臅r(shí)間要求相對1中要低一點(diǎn)。接口表中只要檢索到數(shù)據(jù)就推送給第三方平臺。一般每次傳輸數(shù)據(jù)量不是很多,但很頻繁。

缺點(diǎn):當(dāng)推送數(shù)據(jù)量大時(shí),執(zhí)行任務(wù)時(shí)間可能會較長。主線程會等待線程池中的所有任務(wù)完成。所有每次循環(huán)檢索任務(wù)的時(shí)間間隔可能會出現(xiàn)30S+NS現(xiàn)象。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 河源市| 团风县| 广南县| 休宁县| 莲花县| 哈密市| 高雄县| 舟山市| 泗水县| 正宁县| 凤庆县| 连城县| 科技| 朝阳区| 大新县| 三河市| 镇江市| 静乐县| 平安县| 缙云县| 饶河县| 靖远县| 高邑县| 沙湾县| 上犹县| 平乐县| 垫江县| 长宁区| 高青县| 永德县| 武夷山市| 麟游县| 五家渠市| 延安市| 叶城县| 云阳县| 岢岚县| 阳高县| 德庆县| 莎车县| 新源县|