Олон урсгал ямар хэрэгтэй вэ?

C# хэлний олон урсгал буюу Multithreading ухагдхууны талаар аьч үзье. Сэдэв өргөн хүрээтэй, нарийн, хүндэвтэр учраас нилээд хэдэн хичээлийг хамран судлах болно. Multithreading ухагдхууныг практик ажилд ихээр тохиолддог энгийн жишээнээс эхлэн авч үзье. Бидэнд удаан хугацаанд биелэгдэх ажиллагааг эхлүүлээд түүний явцыг хянах хэрэгтэй боллоо гэе.

Үүнийг загварчлахын тулд прогресс бар, Эхлэх, Зогсоох гэсэн хоёр товч бүхий энгийн форм үүсгэе.

Эхлэх товч ажиллагааг эхлүүлнэ гэдэг нь ойлгомжтой. Харин Зогсоох товч ажиллагааг дуусаагүй байхад зогсоох үүрэгтэй. C# дээр програм хэрхэн үүсгэх, формыг яаж зурахыг та өөрөө сайн мэдэж байгаа гэж бодож байна. Програмын үндсэн класс бол

using System;
using System.Threading;

namespace MultiThread
{
    class Worker
    {
        private bool _cancelled = false;

        public void Cancel()
        {
            _cancelled = true;
        }

        public void Work()
        {
            for (int i = 0; i <= 99; i++)
            {
                if (_cancelled)
                    break;
                Thread.Sleep(50);
                ProcessChanged(i);
            }
            WorkCompleted(_cancelled);
        }

        public event Action<int> ProcessChanged;

        public event Action<bool> WorkCompleted;
    }
}

код бүхий ямар нэгэн удаан хугацаанд биелэгдэх ажиллагааг үзүүлэх Worker юм. Класс хэсэг элементээс бүрдэнэ. Эхнийх нь бол ажиллагааг цуцлагдсан эсэхийг заах private хэлбэрийн _cancelled талбар. Талбарт утга олгох Cancel нээлттэй арга удаан хугацаанд биелэгдэх ажиллагааг програмаас зогсоох командыг өгөхөд _cancelled талбарт true утгыг өгөх юм. Классын үндсэн арга Work урт хугаацаатай хийгдэх ажиллагааг төлөөлнө. Арга ердийн цикл эхлүүлээд цикл дотроо _cancelled талбарыг шалгана. Хэрвээ талбарын утга true буюу ажиллагааг цуцалсан бол циклийн ажиллагааг тэр дор нь break командаар зогсооно. Цааш Thread.Sleep(50) командаар бид хийгдэж байгааг ажиллагааг харуулж байгаа хэрэг. Энд урсгал эсхүл багцтай /thread/ ажилладаг эхний аргатай танилцаж байгаа. Sleep арга тухайн үед ажиллаж байгаа урсгалыг заагдсан тооны миллисекундээр зогсоодог. Кодод бид ажиллагааны логикийг төлөөлүүлэн thread -ыг 50 миллисекунд зогсоосон хэрэг. Бодит програмд үүний оронд ямар нэгэн үйлдлийг хийх нь ойлгомжтой. Програм тодорхой үйлдлийг хийсний дараа үйл явцыг ажиглахаар /сонсох/ бүртгүүлсэн бүртгүүлэгчдэд мэдэгдэхийн тулд зохих ажиллагааны үйл явцыг дуудах хэрэгтэй. Циклээс гараагүй учраас ажиллагаа нэг алхамаар урагшилсанг мэдэгдэхийн тулд ProcessChanged үйл явцад циклийн тоолуурыг дамжуулан дуудна. Цикл break командаар эсхүл ердийн явцаараа дууссан эсэхээс үл хамааран WorkCompleted үйл явцад бүртгүүлсэн бүх бүртгүүлэгчдэд ажиллагаа ердийн эсхүл цуцлагдсанг мэдэгдэхийн тулд түүнд _cancelled талбарын утгыг дамжуулан дуудна. Классын төгсгөлд үйл ажиллагааны явцыг ажиглагчдад мэдээллэх ProcessChanged, WorkCompleted хоёр үйл явцыг /event/ зарласан. ProcessChanged үйл явц ажиллагаа ямар нэгэн байдлаар урагшилсанг харин WorkCompleted нь ажиллагаа дууссанг илтгэнэ. Үндсэн классын ажиллагааны логик энгийн учраас таныг ойлгосон гэж үзээд програмын формын кодыг

namespace MultiThread
{
    public partial class MainForm : Form
    {
        private Worker _worker;

        public MainForm()
        {
            InitializeComponent();

            butStart.Click += butStart_Click;
            butStop.Click += butStop_Click;
        }

        private void butStart_Click(object sender, EventArgs e)
        {
            _worker = new Worker();
            _worker.ProcessChanged += _worker_ProcessChanged;
            _worker.WorkCompleted += _worker_WorkCompleted;

            butStart.Enabled = false;

            _worker.Work();
        }

        private void _worker_ProcessChanged(int progress)
        {
            progressBar.Value = progress;
        }

        private void _worker_WorkCompleted(bool cancelled)
        {
            string message = cancelled ? "Ажиллагаа цуцлагдсан" : "Ажиллагаа дууссан";
            MessageBox.Show(message);
            butStart.Enabled = true;
        }

        private void butStop_Click(object sender, EventArgs e)
        {
                  if (_worker != null)
                    worker.Cancel();
        }
    }
}

харцгаая. Эхлээд програмын бүх ажиллагаа нэг багцад /thread/ явагдах синхрон үйл ажиллагааг авч үзье. Формд үндсэн Worker класс төрлийн _worker хувьсагчийг зарласан. MainForm аргад формын Эхлэх, Зогсоох хоёр товчийг дарах үйл явцад бүртгүүлсэн. Үндсэн ажиллагаа butStart_Click аргад явагдана. Аргад Worker классын хувийг /обьект/ үүсгээд түүний ProcessChanged, WorkCompleted үйл явцуудад бүртгүүлнэ. Дараа нь Эхлэх товчийг дарсны дараа хэрэглэгч түүнийг форм дээрээс дахин дахин даруулахгүйн тулд butStart.Enabled = false; гэж идэвхигүй болгоод Worker классын Work аргыг дуудан ажиллагааг эхлүүлнэ. Worker классын үйл явцуудын боловсруулагчид юу хийгдэх вэ? WorkCompleted үйл явц Worker классын ажиллагаа дууссаны дараа үүснэ. Бид ажиллагааг цуцалсан эсэх cancelled хувьсагчийн утга true байвал Ажиллагаа цуцлагдсан харин утга false байвал Ажиллагаа дууссан гэсэн мэдээллийг үзүүлнэ. Үүгээр таны програмын ажиллагааны төлвөөс хамааран ямар ажиллагааг хийхийг харуулах гэсэн юм. Сургалтын жишээнд бид энгийн байлгах үүднээс текстийг дэлгэц дээр харуулаад хэрэглэгч ажиллагааг дахин явуулах боломжийг хангах зорилгоор Эхлэх товчийг идэвхитэй болгосон. ProcessChanged үйл явцын боловсруулагчид прогрес барын утганд түүнд дамжин ирсэн параметрийн утгыг олгосон. Зогсоох товчийг дарахад butStop_Click арга дуудагдах бөгөөд Worker классын хувь /обьект/ _worker үүссэн байвал түүний Cancel аргыг дуудна. Кодыг ажлуулаад Эхлэх товчийг дарвал

ажиллагаа явагдаж байгааг прогресс бар харуулах боловч бид формыг удирдаж чадахгүй. Хэдийгээр Зогсоох товч идэвхитэй байгаа ч түүн дээр даралт хийх боломжгүй. Програм синхрон горимд буюу форм, ажиллагааны процесс хоёр нэг багцад /thread/ ажиллаж байхад үндсэн процесс форм дээрх ямар нэгэн үйлдлийг бүрэн хаадаг. Өөрөөр хэлбэл хэрэглэгчийн форм дээр хийсэн үйлдлийг ердөө хүлээн авахгүй. Яагаад гэвэл Эхлэх товчийг даран ажиллагааг эхлүүлсний дараа бүх нөөцийг тухайн ажиллагаанд өгөөд график интерфейст юу ч үлдээгүйтэй холбоотой. Иймээс Эхлэх товчийг даран эхлүүлж буй ажиллагааг тусдаа урсгалд /thread/ явуулах хэрэгтэй гэсэн дүгнэлтэд хүрнэ.

Дараагийн хичээлүүдэд олон урсгалыг үүсгэн удирдах аргуудын талаар дэлгэрэнгүй авч үзэх болно.

Мэдээлэл таалагдсан бол найзуудтайгаа хуваалцаарай.

  Нээгдсэн тоо: 7872 Нийтийн

Юуны өмнө ОХП-ын хэлүүд болон C# хэлэнд байдаг тодорхой суурь ухагдхууны талаар ойлголтыг авах хэрэгтэй. ОХП-ын хэлэнд бараг бүх обьектууд өгөгдлийн төрлүүд байдаг.

  • Хувьсагч гэдэг нь төрөл бүрийн утгуудыг авч болдог дараа нь тэдгээрийг өөр төрлийн утгаар өөрчилж болдог хэлний элемент юм. Иймээс түүнийг хувьсагч гэж нэрлэдэг. Тогтмол утга гэж бас байдаг. Тогтмол утга нь хувьсагчаас ялгаатай нь өөрийн утгаа компиляц хийх үед ганц удаа аваад тухайн утгаа дахин өөрчилдөггүй. Хувьсагч гэдгийг ямар нэгэн зүйлийг эсхүл тухайн зүйл хаана байгааг заах мэдээллийг хадгалж болдог хайрцагтай зүйрлэж болно.
  • Өгөгдлийн төрөл гэдгийг хувьсагч авч болох утгуудын олонлог гэж ойлгоно. Хэрвээ бид хувьсагчийг бүхэл тоон төрлийнх гэж заавал түүнд зөвхөн бүхэл тоог эсхүл логик төрлийнх гэвэл зөвхөн логик утгыг авна гэсэн үг. Өөрөөр хэлбэл хувьсагч өөрийн төрөлд багтах утгуудын олонлогоос л утгаа авах ёстой гэсэн үг.
  • Обьект гэдэг нь хувьсагч авсан тодорхой утга эсхүл тухайн утгыг авах холбоосын утгыг хувьсагчид олгосонг хэлнэ. Энэ ойлголт нь ОХП-ын үндсэн гол ойлголт байдаг.

  Нээгдсэн тоо: 58 Төлбөртэй

Үйл явдал /event/ тодорхой үйлдэл хийгдсэн талаар системд мэдэгддэг. Хэрвээ бид энэхүү үйлдлийг ажиглах хэрэгтэй бол яг энд үйл явцыг хэрэглэж болно.
Жишээ болгоод банкны дансыг тодорхойлох 

class Account
{
    // дансны үлдэгдэл
    public int Sum { get; private set; }
    // байгуулагчаар дансны эхний үлдэгдлийг тогтооно
    public Account(int sum) => Sum = sum;
    // дансанд мөнгө хийх
    public void Put(int sum) => Sum += sum;
    // данснаас мөнгө авах
    public void Take(int sum)
    {
        if (Sum >= sum)
        {
            Sum -= sum;
        }
    }
}

классийг аваад үзье. Байгуулагчид Sum шинжид хадгалагдах эхний үлдэгдлийг тогтооно. Put аргаар дансанд мөнгө хийнэ.

  Нээгдсэн тоо: 1786 Төлбөртэй

Өмнөх хичээлүүдэд ашигласан графикийн интерфейстэй програмд олон урсгалын хэрэгжүүлэлтийг өөр аргуудаар хэрхэн хийж болохыг харцгаая. WinForms санд дэвсгэр эсхүл нүүр талын /фон/ ажиллагааг гүйцэтгэхэд зориулагдсан BackgroundWorker гэдэг компонент

хэрэгслүүдийн самбарын Components хэсэгт бий.

  Нээгдсэн тоо: 259 Бүртгүүлэх

C# -д тоо, мөр гээд стандарт төрлийн утгуудаас гадна ямар нэгэн өгөгдөл, утга байхгүйг заах тусгай null утга гэж бий. Холбоосын төрлүүд анхдагч утгаар null утгыг авдаг. C# 8.0 хувилбар хүртэл бүх холбоосын төрлүүдэд null утгыг

string name = null;
Console.WriteLine(name);

олгож болдог байсан. Харин C# 8.0 хувилбараас холбоосын nullable төрөл (nullable reference types) болон холбоосын nullable төрлийг ашиглаж болох nullable aware context - буюу nullable-контекст ойлголтыг оруулсан.  
null утга авч болох холбоос төрлийн хувьсагч болон параметрийг тодорхойлохын тулд төрлийн нэрийн ард ? (асуултын тэмдэг) -ийг тавина. Жишээ нь

string? name = null;
Console.WriteLine(name);    // юу ч үзүүлэхгүй

Үйл явдал /event/ тодорхой үйлдэл хийгдсэн талаар системд мэдэгддэг. Хэрвээ бид энэхүү үйлдлийг ажиглах хэрэгтэй бол яг энд…

Нээгдсэн тоо : 58

 

Манай төсөл олон хуудсуудтай болон тэдгээрийн хооронд динамикаар шилжилт хийж байгаа ч тухайн үед шилжилт хийгдсэн хуудаст тохирох…

Нээгдсэн тоо : 90

 

Зочин (Visitor) паттерн классуудыг өөрчлөхгүйгээр тэдгээрийн обьектуудын үйлдлийг тодорхойлох боломжийг олгоно. Зочин хэвийг ашиглахдаа классуудын хоёр ангилалыг тодорхойлно.…

Нээгдсэн тоо : 86

 

Лямбда-илэрхийлэл нь нэргүй аргын хураангуй бичилтийг илэрхийлнэ. Лямбда-илэрхийлэл утга буцаадаг, буцаасан утгыг өөр аргын…

Нээгдсэн тоо : 203

 

Кодийн сайжруулалт /рефакторинг/ хичээлээр програмийн кодоо react -ийн зарчимд нийцүүлэн компонентод салгасан.…

Нээгдсэн тоо : 245

 

Хадгалагч (Memento) хэв обьектын дотоод төлвийг түүний гадна гаргаж дараа нь хайрцаглалтын зарчмыг зөрчихгүйгээр обьектыг сэргээх боломжийг олгодог.

Нээгдсэн тоо : 254

 

Делегаттай нэргүй арга нягт холбоотой. Нэргүй аргуудыг делегатийн хувийг үүсгэхэд ашигладаг.
Нэргүй аргуудын тодорхойлолт delegate түлхүүр үгээр…

Нээгдсэн тоо : 297

 

Математикт харилцан урвуу тоонууд гэж бий. Ямар нэгэн тооны урвуу тоог олохдоо тухайн тоог сөрөг нэг зэрэг дэвшүүлээд…

Нээгдсэн тоо : 285

 

Төсөлд react-router-dom санг оруулан чиглүүлэгчдийг бүртгүүлэн тохируулсан Санг суулган тохируулах хичээлээр бид хуудас…

Нээгдсэн тоо : 369

 
Энэ долоо хоногт

функцийн интервал дахь хамгийн бага утгыг ол.

Нээгдсэн тоо : 855

 

Зөв дөрвөн өнцөгт пирамидын өндөр 4. Хажуу ирмэг суурийн хавтгайд 30 градусын өнцгөөр налсан бол пирамидын хажуу ирмэгийг ол.

Нээгдсэн тоо : 1848

 

бол M·N=?

Нээгдсэн тоо : 1161