Multithreading în C#: beneficii, elemente de bază și bune practici

Publicat: 2023-06-01

Cuprins

Ce este programarea multi-threaded

Multithreadingul este un concept fundamental în ingineria software. În C#, programarea multithreaded este esențială pentru dezvoltatorii de software care lucrează cu .NET Framework. Dezvoltatorii folosesc pe scară largă multithreading în C# , deoarece le permite să creeze aplicații complexe și receptive în mod eficient.

Acest blog oferă o privire de ansamblu asupra multithreading-ului c#, în timp ce, în același timp, analizează și modul în care programatorii pot crea și gestiona cu ușurință firele. Include, de asemenea, beneficiile utilizării multithreading-ului și diferitelor modele de threading disponibile în C#.

Beneficiile și avantajele programării cu mai multe fire

Când este executat simultan, multithreadingul îmbunătățește eficiența aplicațiilor. Cele mai comune beneficii ale firului C# includ următoarele:

  • Performanță îmbunătățită a aplicației: cu ajutorul multithreading-ului, aplicațiile rulează mai rapid cu mai multe sarcini rulând în același spațiu.În totalitatea sa, reduce timpul de execuție și lasă loc unor sarcini multiple.
  • Debit crescut: Multitasking în C# îmbunătățește debitul aplicațiilor.Când două fire diferite rulează simultan, se poate economisi timp și resurse.
  • Reactivitate îmbunătățită: cu ajutorul multithreading-ului, un utilizator poate accesa front-end-ul aplicației în timp ce programul rulează în fundal.
  • Utilizare sporită a resurselor: Multithreading permite utilizatorilor să acceseze resursele sistemului mai eficient.De exemplu, firele de execuție pot partaja resurse precum fișiere, memorie și dispozitive I/O, deschizând calea către eficiență.
  • Programare mai accesibilă: Multithreading permite o programare mai ușoară, deoarece utilizatorii pot scrie fire de execuție independent.De asemenea, permite utilizatorilor să depaneze și să testeze aplicații izolat.
  • Comunicare optimizată: Sincronizarea firelor permite o comunicare mai bună de la proces la proces.Poate fi folosit pentru o comunicare mai accesibilă între fire.

În primul rând, afectează obiectele individuale care pot fi sincronizate. În al doilea rând, poate fi folosit cu clasa System.Threading și Interlocked.

Concepte de bază de multithreading în C#

Multithreading permite utilizatorilor să efectueze mai multe sarcini simultan, cu ajutorul mai multor nuclee de procesor. Iată conceptele de bază folosite în multithreading:

  • Threads: Thread-urile sunt unitățile de bază în multithreading care ajută la executarea unui proces.Acestea sunt căi de execuție în cadrul unui anumit program care pot rula concomitent cu alte fire.

În C#, putem găsi două tipuri de fire de execuție, și anume fire în prim-plan și în fundal. Clasa medie de fire include un nume, prioritate, isAlive, ThreadState, Start(), Suspend(), Resume() și Join().

  • Pool de fire: un pool de fire este un fir care ajută la executarea sarcinilor.Permite sistemului de operare să refolosească firele de execuție existente și minimizează riscul unor posibile costuri generale.
  • Sincronizare: Sincronizarea trece cu vederea accesul la alte fire pentru operațiuni multiple.Este un proces esențial pentru a menține integritatea datelor și a preveni cheltuielile generale.
  • Deadlock: un deadlock este o eroare care apare atunci când două fire de execuție împărtășesc resurse și încearcă să continue fără succes.Poate provoca înghețarea sistemului sau chiar duce la un timp de așteptare.
  • Programare asincronă: programarea asincronă permite rularea mai multor sarcini în fundal, permițând, în același timp, firului principal să ruleze fără întrerupere.Acesta deschide calea pentru mai multe interfețe de utilizator receptive, îmbunătățind performanța aplicației.

Crearea și rularea thread-urilor

Crearea și rularea pot fi mai ușoare cu aceste exemple. Un exemplu de multithreading C# este dat mai jos:

folosind System;

folosind System.Threading;

program de clasă {

static void Main() {

int workerIndex = 0;

Thread workerThread = nou Thread(new ThreadStart(Worker));

workerThread.Start();

pentru (int mainIndex = 1; mainIndex <= 10; mainIndex++) {

Console.WriteLine(„Fir principal: {0}”, mainIndex);

Thread.Sleep(200);

}

workerThread.Join();

}

static void Lucrător() {

pentru (int workerIndex = 1; workerIndex <= 10; workerIndex++) {

Console.WriteLine(„Fir de lucru: {0}”, workerIndex * 2);

Thread.Sleep(200);

}

}

}

Ieșire:

Firul principal: 1

Firul de lucru: 2

Firul principal: 2

Firul de lucru: 4

Firul principal: 3

Firul de lucru: 6

Firul principal: 4

Firul de lucru: 8

Firul principal: 5

Firul de lucru: 10

Firul principal: 6

Firul de lucru: 12

Firul principal: 7

Firul de lucru: 14

Firul principal: 8

Firul de lucru: 16

Firul principal: 9

Firul de lucru: 18

Firul principal: 10

Firul de lucru: 20

Explicație: În această ieșire, ambele fire lucrează concomitent pentru a tipări numerele de la 1 la 10 și de la 2 la 20, acestea din urmă dublate de la indexul buclei.În acest exemplu, a fost utilizată metoda C# (Thread.Sleep).

În același mod, ne vom uita la un alt exemplu de fir C# folosind firul din prim-plan:

folosind System;

folosind System.Threading;

program de clasă {

static void Main() {

Thread myThread = nou Thread(Worker);

myThread.Start();

Console.WriteLine(„Fila principală: începută”);

pentru (int i = 1; i <= 5; i++) {

Console.WriteLine(„Fire principală: Count {0}”, i);

Thread.Sleep(500);

}

Console.WriteLine(„Fii principal: Încheiat”);

}

static void Lucrător() {

pentru (în j = 1; j <= 5; j++) {

Console.WriteLine(„Fire de lucru: Număr {0}”, j * 3);

Thread.Sleep(750);

}

Console.WriteLine(„Fii de lucru: Încheiat”);

}

}

Ieșire:

Thread principal: A început

Thread de lucru: numără 3

Subiect principal: Numărare 1

Fire de lucru: Număr 6

Subiect principal: Numărul 2

Thread de lucru: numără 9

Subiect principal: Numărare 3

Fire de lucru: numără 12

Subiect principal: numără 4

Fire de lucru: numără 15

Subiect principal: Numărare 5

Lucrător Thread: Încheiat

Thread principal: Încheiat

Explicație: Această ieșire arată cum funcționează cele două fire simultan.Deoarece firele principale și de fundal funcționează în paralel, firul principal imprimă numere de la 1 la 5. Firul de lucru tipărește multipli de la 3 la 15.

Verificați cursurile de dezvoltare software la upGrad pentru a îmbunătăți competențele.

Citiți articolele noastre populare legate de dezvoltarea software

De ce să înveți să codificăm? Cum să înveți să codificăm? Cum se instalează o versiune specifică a pachetului NPM? Tipuri de moștenire în C++ Ce ar trebui să știți?

Sincronizarea firelor

Sincronizarea firelor implică coordonarea colectivă a mai multor fire dintr-un program. Acesta asigură că programul este executat într-o anumită ordine, oferind acces la resursele partajate.

În C#, se face folosind primitive de sincronizare, cum ar fi cuvântul cheie lock, obiectele de sincronizare și clasa Interlocked.

Un exemplu de sincronizare a firului de execuție C# este dat mai jos:

Utilizarea sistemului;

Utilizarea System.Threading;

clasa TablePrinter

{

public void PrintTable()

{

incuie (acesta)

{

pentru (int i = 3; i <= 8; i++)

{

Thread.Sleep(200);

Consola.WriteLine(i*5);

}

}

}

}

Programul clasei

{

public static void Main(string[] args)

{

TablePrinter tp = new TablePrinter();

Thread t1 = nou Thread(new ThreadStart(tp.PrintTable));

Thread t2 = new Thread(new ThreadStart(tp.PrintTable));

t1.Start();

t2.Start();

}

}

Ieșire:

15

20

25

30

35

40

45

50

55

60

Explorați cursurile noastre gratuite de dezvoltare software

Fundamentele cloud computing Noțiuni de bază JavaScript de la zero Structuri de date și algoritmi
Tehnologia blockchain Reacționează pentru începători Bazele de bază ale Java
Java Node.js pentru începători JavaScript avansat

Blocaje

Blocajele în multithreading apar atunci când cel puțin două sau mai multe două fire depind de un set de resurse. Când un fir se suprapune pe traseul către ajutor în timp ce celălalt încearcă să facă același lucru, devine un impas.

De exemplu, dacă Thread A are o blocare pe Resursa 1 și așteaptă să acceseze Resursa 2 în timp ce Thread B așteaptă Resursa 1, poate duce la un impas.

Un exemplu este dat mai jos:

folosind System;

folosind System.Threading;

spațiu de nume deadlockincsharp

{

clasă publică Exemplu

{

obiect static doar pentru citire firstLock = obiect nou ();

obiect static readonly secondLock = obiect nou ();

static void ThreadJob()

{

Console.WriteLine(„\t\t\t\tLocking firstLock”);

blocare (firstLock)

{

Console.WriteLine(„\t\t\t\tLocked firstLock”);

Thread.Sleep(1500);

Console.WriteLine(„\t\t\t\tLocking secondLock”);

blocare (secondLock)

{

Console.WriteLine(„\t\t\t\tLocked secondLock”);

}

Console.WriteLine(„\t\t\t\tReleased secondLock”);

}

Console.WriteLine(„\t\t\t\tEliberat primulLock”);

}

static void Main()

{

Thread nou(nou ThreadStart(ThreadJob)).Start();

Thread.Sleep(1000);

Console.WriteLine(„Blocarea secundăLock”);

blocare (secondLock)

{

Console.WriteLine(„Locked secondLock”);

Console.WriteLine(„Blocare primulLock”);

blocare (firstLock)

{

Console.WriteLine(„Blocat primulLock”);

}

Console.WriteLine ("Eliberat primul blocare");

}

Console.WriteLine(„S-a lansat secondLock”);

Console.Read();

}

}

}

Ieșire:

Se blochează secondLock

SecondLock blocat

Închiderea întâiLock

Blocat în primul rând

S-a eliberat firstLock

S-a eliberat secondLock

Abilități de dezvoltare software la cerere

Cursuri JavaScript Cursuri de bază Java Cursuri de Structuri de Date
Cursuri Node.js Cursuri SQL Cursuri de dezvoltare full stack
Cursuri NFT Cursuri DevOps Cursuri de Big Data
Cursuri React.js Cursuri de securitate cibernetică Cursuri de cloud computing
Cursuri de proiectare baze de date Cursuri Python Cursuri de criptomonede

Pool-uri de fire

Pool-urile de fire ajută la gestionarea mai multor fire de execuție într-un mediu cu mai multe fire în C#. Acestea asigură că toate firele de execuție au acces la resurse controlate fără a da naștere la blocaje.

Un manager de pool de fire are grijă de pool-ul de fire, unde este responsabil pentru crearea, distrugerea și programarea firelor.

Iată un exemplu de pool de fire care utilizează TPL (Biblioteca paralelă de activități):

folosind System;

folosind System.Threading.Tasks;

Programul clasei

{

static void Main()

{

Sarcină<șir> sarcină = Sarcină.Factory.StartNew<șir>

(() => DownloadString(„http://www.example.com/”));

șir rezultat = sarcină.Rezultat;

Console.WriteLine(rezultat);

Console.Read();

}

șir static DownloadString(șir uri)

{

folosind (var wc = new System.Net.WebClient())

return wc.DownloadString(uri);

}

Ieșire:

Ieșirea depinde de conținutul disponibil pe pagina web. Acest program va asigura descărcarea conținutului de pe pagina web de la adresa URL specificată. Apoi le va imprima.

Programare asincronă cu biblioteca paralelă de sarcini (TPL)

Biblioteca paralelă de sarcini (TPL) este un instrument puternic pentru a trata APIS și tipurile publice. Se ocupă de System.Threading și System.Threading.Tasks .

.NET Framework 4 oferă API-uri la nivel de limbaj și cadru pentru dezvoltatorii care doresc să scrie cod paralel. Cu ajutorul TPL, programarea asincronă permite programelor să ruleze fără a bloca firul principal.

Iată un exemplu de programare asincronă cu TPL:

Sarcină<șir> sarcină = Sarcină.Factory.StartNew<șir>(() => {

returnează „rezultat”;

});

string result = task.Result;

Sarcină asincronă MyMethod() {

șir rezultat = așteptare sarcină;

}

Consultațicursurile noastre gratuite de tehnologie pentru a obține un avantaj față de concurență.

Cele mai bune practici pentru multithreading în C#

Multithreading-ul poate economisi timp în termeni de performanță și multitasking. Pentru a afla mai multe despre cum funcționează multithreadingul, puteți opta pentru un Master în Științe în Informatică de la LJMU .

Iată câteva bune practici pentru a ajuta utilizatorii să economisească timp și să înregistreze cea mai mare eficiență.

  • Utilizați colecții thread-safe: colecțiile concurente ale .NET Framework oferă o versiune thread-safe a fiecărei colecții, ceea ce face mai ușor ca multithreading să funcționeze eficient.Aceste colecții includ liste și interogări și dicționare.
  • Implementați sincronizarea firelor: utilizatorii pot implementa rapid blocări, monitoare și semafore datorită naturii instrumentelor de fire.
  • Utilizați thread-pooling: Multithreading poate fi mai ușor și mai eficient pentru sisteme, datorită marii majorități a thread-pooling-ului făcut de utilizatori.În același timp, utilizatorii îl pot folosi pentru a crea fire automate.
  • Utilizați stocarea locală a firelor de execuție: în timp ce practicați mai multe fire de execuție, asigurați-vă accesul la o anumită resursă, optimizând stocarea locală a firelor de execuție și oferind acces la mai multe fire de execuție.
  • Evitați partajarea stărilor mutabile: stările mutabile partajate vor duce doar la erori și condiții de cursă, care pot fi dificile.Asigurați-vă că evitați stările mutabile cu orice preț.
  • Utilizați modelul asincron: metodele asincrone vă ajută să implementați mai multe sarcini în paralel fără a le porni din nou sau a le lăsa în coadă.
  • Evitați blocajele: pot fi așteptate blocaje atunci când executați programe care utilizează multithreading.Când scrieți un program, încercați să rulați un fir numai după altul, evitând blocajele.
  • Utilizați jetoane de anulare: jetoanele de anulare permit terminarea firelor de execuție fără probleme și evită blocajul.

Explorați cursurile noastre populare de inginerie software

Master în Informatică de la LJMU și IIITB Programul de certificat de securitate cibernetică Caltech CTME
Bootcamp pentru dezvoltare completă Programul PG în Blockchain
Program Executive PG în Full Stack Development
Vezi mai jos toate cursurile noastre
Cursuri de Inginerie Software

Concluzie

Multithreadingul în C# rămâne un concept esențial cu modelul său de înaltă eficiență la locul de muncă. Oferă o modalitate flexibilă pentru programatori de a împărți volumul de lucru al unui program în mai multe sarcini care rulează simultan și independent.

Deși multithreading-ul poate fi extrem de benefic, poate duce la potențiale obstacole dacă nu este implementat cu atenție.

Cu bugetul global pentru software-ul întreprinzător depășind 856 de miliarde de dolari în perioada 2009-2023, dezvoltarea de software promite o carieră strălucitoare pentru dezvoltatori.

Aplicați acum pentru Bootcampul de dezvoltare software Full Stack de la upGrad ! Un curs de dezvoltare full stack poate fi piatra de temelie pentru dezvoltatorii care doresc să-și dezvăluie potențialul în informatică.

1. Ce este programarea multithreaded?

Programarea cu mai multe fire este un proces care implică execuția de programe care utilizează mai multe fire simultan. Permite utilizatorilor de pe front end să utilizeze mai multe copii ale programului care rulează pe computer fără întrerupere.

2. Care este diferența principală dintre fir și proces?

Un proces implică de obicei un program în stare de execuție, în timp ce un fir constă dintr-un proces dintr-un sub-proces.

3. Care este diferența dintre un fir și o sarcină în C#?

Un thread în C# se ocupă cu construirea și gestionarea unui pool de fire destinate programării. Pe de altă parte, o sarcină reprezintă o funcție asincronă care funcționează în fundal.