Chủ đề php

Trong bài học này, chúng ta sẽ làm quen với khái niệm luồng (luồng) và các kỹ thuật thiết lập trình đa luồng (lập trình đa luồng) của. NET framework thường được sử dụng để phát triển các ứng dụng mạng

NỘI DUNG CỦA BẢNG

Chủ đề

thread kí hiệu

Khi thiết lập trình theo mô hình mệnh lệnh hoặc hướng đối tượng, chúng ta xây dựng các phương thức và chỉ định trình tự (theo thời gian) thực hiện các phương thức đó

Trình tự (lời gọi) thực hiện các phương thức khi thiết lập trình như vậy được gọi là dòng điều khiển (luồng điều khiển) hoặc dòng thực thi (luồng thực thi). Dòng điều khiển cho phép chúng ta cấu hình thứ tự thực hiện (và tự thực hiện trong đầu. ) các phương thức khi chương trình chạy

Khi chương trình thực sự chạy, bố trí hệ thống điều hành cho CPU lần cuối cùng thực hiện các lệnh theo trật tự đã được chỉ định trong mã. Việc bố trí này được thực hiện bởi một chương trình đặc biệt của hệ thống điều hành được gọi là lịch trình (bộ lập lịch). Chuỗi lệnh mà bộ lập lịch có thể quản lý độc lập được gọi là một luồng thực thi (luồng thực thi)

Có thể cấu hình phân luồng thực thi như một người công nhân chuyên thực hiện các nhiệm vụ mà chương trình giao. Nếu có một công nhân thì tại mỗi thời điểm chỉ có thể thực hiện được một nhiệm vụ (đơn luồng). Nếu muốn thực hiện nhiều công việc cùng lúc thì phải thuê thêm công nhân (đa luồng)

Chủ đề và Quy trình

Khi một chương trình được tải vào bộ nhớ và thực thi, hệ thống điều hành bố trí cho chương trình một “không gian” độc lập (và biệt lập) và ít nhất là một luồng thực thi cho các lệnh. “Không gian” dành cho chương trình như vậy được gọi là tiến trình (tiến trình)

Chúng ta phân biệt process và thread ở các điểm sau

Thread tồn tại như một bộ phận của process. Trong một process phải có ít nhất một thread. Khi tạo ra một process thì cũng đồng thời tạo ra thread chính của process. Giao diện của một ứng dụng luôn do luồng chính tạo ra

Quá trình tồn tại biệt lập. Việc trao đổi thông tin giữa các quy trình khá khó khăn, ví dụ, phải thông qua dịch vụ mạng hoặc cơ chế truyền thông liên tiến trình của hệ thống điều hành. Trong khi đó, các luồng tồn tại trong cùng một quy trình cùng chia sẻ tài nguyên chung và các trạng thái của quy trình (như không có bộ nhớ)

Từ góc nhìn lập trình, các luồng có thể được coi là mã của cùng một chương trình và có thể sử dụng các biến chung với nhau, còn các quy trình giống như các chương trình ứng dụng khác nhau

Mô hình đơn luồng (Single threading )

Mặc định trong mỗi quy trình thường chỉ tạo ra một luồng thực thi. Luồng thực thi được tạo ra lần đầu tiên giống với quy trình được gọi là luồng chính (luồng chính). Chỉ có một luồng thực thi đồng nghĩa với công việc tại mỗi thời điểm chỉ có duy nhất một lệnh được thực hiện. Phương thức tiếp theo chỉ bắt đầu thực hiện khi phương thức trước đó kết thúc

Một ứng dụng chỉ sử dụng một luồng duy nhất được gọi là ứng dụng đơn luồng (luồng đơn). Trong suốt quá trình học lập trình socket đến giờ (cả trong học lập trình cơ bản) chúng ta đều chỉ xây dựng các ứng dụng theo mô hình đơn dòng

Chủ đề php
Chủ đề php
Ứng dụng Udp theo mô hình đơn luồng (luồng đơn)

Các ứng dụng này có chung một điểm đặc biệt. tại mỗi thời điểm, máy chủ chỉ có thể phục vụ duy nhất một máy khách. Nếu lượng khách hàng nhỏ và thời gian thực hiện công việc không dài, thì đây có thể không phải là một nhược điểm lớn. Tuy nhiên, nếu số lượng máy khách tăng lên hoặc khối lượng tính toán để phục vụ cho mỗi máy khách tăng lên (ví dụ: khi tải một tệp lớn lên), lập trình đơn luồng cho máy chủ là không phù hợp

Đối với client, giao diện của ứng dụng luôn thực hiện luồng chính “vẽ” ra. Khi phát lệnh thực thi trong thời gian dài (ví dụ: khi tải lên/tải xuống tệp lớn), giao diện có thể hoàn toàn bị treo. Điều này ảnh hưởng đến trải nghiệm của người dùng

Các lý do trên cùng với một số vấn đề khác đưa ra yêu cầu phải xây dựng các chương trình với nhiều luồng thực thi để đảm bảo thực hiện nhiều công việc đồng thời. Các ứng dụng có khả năng thực hiện cùng lúc nhiều công việc như vậy được gọi là ứng dụng đa luồng (đa luồng)

Mô hình đa luồng (Đa luồng)

Mô hình ứng dụng đa luồng gặp chủ yếu trong các hệ điều hành đa nhiệm. Đây là mô hình thiết lập chương trình và thực thi được sử dụng rất phổ biến. Mô hình này cho phép tạo ra và sử dụng nhiều luồng trong khuôn khổ của một quy trình. Các chủ đề chia sẻ tài nguyên của quy trình nhưng lại có thể thực thi độc lập

So với mô hình đơn luồng, mô hình này có nhiều ưu điểm hơn

  • Khả năng tương tác tốt hơn với người dùng do ứng dụng không bị “treo” khi thực hiện các nhiệm vụ kéo dài. Khả năng có lợi lớn khi phát triển chương trình client
  • Máy chủ có khả năng phục vụ đồng thời nhiều máy khách
  • Thực thi nhanh hơn trên nhiều hệ thống CPU hoặc nhiều lõi, vốn sử dụng phổ biến hiện nay
  • Giảm mức tiêu thụ tài nguyên khi phục vụ nhiều khách hàng
  • Tận dụng tốt hơn khả năng của hệ thống

Ở tua ngược lại, mô hình đa luồng cũng có những nhược điểm

  • Vấn đề đồng bộ hóa khi nhiều chủ đề cùng chia sẻ không gian địa chỉ. Việc này có thể dẫn đến tài nguyên xung quanh, trạng thái bế tắc và khóa trực tiếp (các luồng khóa xen kẽ nhau)
  • Lỗi từ một luồng có thể làm hỏng cả quá trình

Thực hành. Xây dựng tệp tải lên ứng dụng

Ở phần này, chúng ta sẽ xây dựng một ứng dụng client/server đơn giản cho phép client upload file lên server. Ứng dụng này được thực hiện bằng kỹ thuật lập trình đơn luồng cơ bản đã học. Đây là ứng dụng cơ sở để phần sau chúng ta nâng cấp thành phần máy chủ bằng kỹ thuật thiết lập trình đa luồng

Trong ứng dụng này, chúng tôi tạo ra một giao thức đơn giản, trong đó

Để tải lên một tệp, khách hàng gửi cho máy chủ gói tin có định dạng như sau

Chủ đề php
Chủ đề php
Cấu hình gói tin yêu cầu của khách hàng

Máy chủ sau khi nhận hết dữ liệu sẽ gửi ngược lại máy khách dòng ký tự “200 OK, cảm ơn”

Ứng dụng này sử dụng các kỹ thuật lập trình với luồng mạng và tệp luồng

Chuẩn bị giải pháp

  1. Tạo một giải pháp trống với tên gọi TcpFileUploader
  2. Trong giải pháp tạo hai project (Console App) Client và Server
  3. Thiết lập để gỡ lỗi đồng thời cả máy khách và máy chủ

Chủ đề php
Chủ đề php

Viết code cho Client và Server

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Client
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.Title = "File uploader client";
            Console.Write("Server ip: ");
            var ip = IPAddress.Parse(Console.ReadLine());
            var ep = new IPEndPoint(ip, 1308);
            while (true)
            {
                Console.Write("file > ");
                var path = Console.ReadLine();
                if (File.Exists(path))
                {
                    var fileName = Path.GetFileName(path);
                    var fileNameBytes = Encoding.UTF8.GetBytes(fileName);
                    var fStream = File.OpenRead(path);
                    var client = new TcpClient();
                    client.Connect(ep);
                    var nsStream = client.GetStream();
                    var writer = new BinaryWriter(nsStream);
                    writer.Write(fileNameBytes.Length);
                    writer.Write(fStream.Length);
                    writer.Write(fileNameBytes);
                    var size = 512;
                    var buffer = new byte[size];
                    var count = 0;
                    while (true)
                    {
                        count = fStream.Read(buffer, 0, size);
                        if (count == 0)
                        {
                            fStream.Close();
                            break;
                        }
                        nsStream.Write(buffer, 0, count);
                    }
                    nsStream.Flush();
                    var reader = new StreamReader(nsStream);
                    var response = reader.ReadLine();
                    Console.WriteLine(response);
                    client.Close();
                }
            }
        }
    }
}
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
    class Program
    {
        static readonly string _home = @"E:\TEMP";
        static void Serve(TcpClient client)
        {
            
            var nsStream = client.GetStream();
            var reader = new BinaryReader(nsStream);
            var fileNameLength = reader.ReadInt32();
            var fileDataLength = reader.ReadInt64();
            var fileNameBytes = reader.ReadBytes(fileNameLength);
            var fileName = Encoding.UTF8.GetString(fileNameBytes);
            Console.WriteLine($"File to receive: {fileName}");
            Console.WriteLine($"Bytes to receive: {fileDataLength}");
            var path = Path.Combine(_home, fileName);
            var fStream = File.OpenWrite(path);
            var length = 0L;
            var size = 512;
            var buffer = new byte[size];
            while (length < fileDataLength)
            {
                var count = nsStream.Read(buffer, 0, size);
                fStream.Write(buffer, 0, count);
                length += count;
            }
            Console.WriteLine($"File saved as: {path}");
            Console.WriteLine($"Bytes received: {fStream.Length}");
            Console.WriteLine("-----------");
            fStream.Close();
            var writer = new StreamWriter(nsStream) { AutoFlush = true };
            writer.WriteLine("200 OK, Thank you!");
            client.Close();
        }
        static void Main(string[] args)
        {
            Console.Title = "File uploader server";
            var listener = new TcpListener(IPAddress.Any, 1308);
            listener.Start(10);
            
            while (true)
            {
                var client = listener.AcceptTcpClient();
                Serve(client);                
            }
        }        
    }
}

Chủ đề php
Chủ đề php
Kết quả chạy chương trình File Uploader

Các kỹ thuật thiết lập luồng đa luồng trong. MẠNG LƯỚI

Trong khi áp dụng các kỹ thuật thiết lập trình đa luồng dưới đây, chúng tôi thực hiện một hệ thống logic nhất. Ngay sau khi máy chủ tiếp nhận một liên kết tcp, liên kết này sẽ được chuyển sang một luồng riêng tư để thực hiện tải dữ liệu về máy chủ. Liên kết sẽ đóng lại sau khi hoàn thành nhiệm vụ tải tệp. Luồng chính của máy chủ chỉ làm nhiệm vụ tiếp nhận kết nối tcp từ máy khách

Chủ đề php
Chủ đề php
Mô hình Máy chủ đa luồng

Như vậy, cứ mỗi client kết nối tới sẽ tạo ra một luồng riêng để phục vụ client này. Máy chủ ngay sau khi tạo luồng mới sẽ quay lại chờ tiếp nhận yêu cầu kết nối từ máy khách khác. Bằng cách này, máy chủ có khả năng phục vụ nhiều máy khách

NET framework Hỗ trợ ba phương pháp khác nhau để thiết lập trình đa luồng. sử dụng lớp ThreadPool, lớp BackgroundWorker, lớp Thread

Use ThreadPool

Sử dụng lớp ThreadPool là phương pháp đơn giản nhất để tạo luồng thực thi mới trong. MẠNG LƯỚI. Chúng ta sẽ điều chỉnh mã của phương thức chính của Máy chủ để sử dụng ThreadPool như sau

using System.Threading;
...
static void Main(string[] args)
{
    Console.Title = "File uploader server";
    var listener = new TcpListener(IPAddress.Any, 1308);
    listener.Start(10);
            
    while (true)
    {
        var client = listener.AcceptTcpClient();
        //Serve(client);
        ThreadPool.QueueUserWorkItem(Callback, client);
    }
}
// Xây dựng thêm phương thức Callback
private static void Callback(object state)
{
    var client = state as TcpClient;
    Console.WriteLine($"Starting a new thread: {Thread.CurrentThread.ManagedThreadId}");
    Serve(client);
}

Ở trên chúng ta bổ sung không gian tên using System.Threading;, xây dựng phương thức mới private static void Callback(object state), và sử dụng phương thức QueueUserWorkItem của lớp ThreadPool

Chạy thử nghiệm máy chủ với hai máy khách cùng lúc tải lên hai tệp lớn (1,4G và 1,8G)

Chủ đề php
Chủ đề php
Máy chủ cùng lúc tải hai tệp (1,4G và 1,8G) từ hai máy khách

Nhóm chủ đề là một danh sách các luồng được. NET tạo sẵn và quản lý, giúp việc thiết lập trình đơn đa luồng đơn giản hết mức có thể. Do các thread trong thread pool được tạo sẵn, việc sử dụng các thread này rất đơn giản và hiệu quả. First version of. NET (32 bit) only support 25 thread. Phiên bản mới nhất của. NET (64 bit)Support to the astreme thread

  • 1023 trong Khung 4. 0 (môi trường 32-bit)
  • 32767 trong Khung 4. 0 (môi trường 64 bit)
  • 250 mỗi lõi trong Framework 3. 5
  • 25 mỗi lõi trong Framework 2. 0

To run the method Callbacktrong new stream, only please call

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
    class Program
    {
        static readonly string _home = @"E:\TEMP";
        static void Serve(TcpClient client)
        {
            
            var nsStream = client.GetStream();
            var reader = new BinaryReader(nsStream);
            var fileNameLength = reader.ReadInt32();
            var fileDataLength = reader.ReadInt64();
            var fileNameBytes = reader.ReadBytes(fileNameLength);
            var fileName = Encoding.UTF8.GetString(fileNameBytes);
            Console.WriteLine($"File to receive: {fileName}");
            Console.WriteLine($"Bytes to receive: {fileDataLength}");
            var path = Path.Combine(_home, fileName);
            var fStream = File.OpenWrite(path);
            var length = 0L;
            var size = 512;
            var buffer = new byte[size];
            while (length < fileDataLength)
            {
                var count = nsStream.Read(buffer, 0, size);
                fStream.Write(buffer, 0, count);
                length += count;
            }
            Console.WriteLine($"File saved as: {path}");
            Console.WriteLine($"Bytes received: {fStream.Length}");
            Console.WriteLine("-----------");
            fStream.Close();
            var writer = new StreamWriter(nsStream) { AutoFlush = true };
            writer.WriteLine("200 OK, Thank you!");
            client.Close();
        }
        static void Main(string[] args)
        {
            Console.Title = "File uploader server";
            var listener = new TcpListener(IPAddress.Any, 1308);
            listener.Start(10);
            
            while (true)
            {
                var client = listener.AcceptTcpClient();
                Serve(client);                
            }
        }        
    }
}
0. Trong đó,
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
    class Program
    {
        static readonly string _home = @"E:\TEMP";
        static void Serve(TcpClient client)
        {
            
            var nsStream = client.GetStream();
            var reader = new BinaryReader(nsStream);
            var fileNameLength = reader.ReadInt32();
            var fileDataLength = reader.ReadInt64();
            var fileNameBytes = reader.ReadBytes(fileNameLength);
            var fileName = Encoding.UTF8.GetString(fileNameBytes);
            Console.WriteLine($"File to receive: {fileName}");
            Console.WriteLine($"Bytes to receive: {fileDataLength}");
            var path = Path.Combine(_home, fileName);
            var fStream = File.OpenWrite(path);
            var length = 0L;
            var size = 512;
            var buffer = new byte[size];
            while (length < fileDataLength)
            {
                var count = nsStream.Read(buffer, 0, size);
                fStream.Write(buffer, 0, count);
                length += count;
            }
            Console.WriteLine($"File saved as: {path}");
            Console.WriteLine($"Bytes received: {fStream.Length}");
            Console.WriteLine("-----------");
            fStream.Close();
            var writer = new StreamWriter(nsStream) { AutoFlush = true };
            writer.WriteLine("200 OK, Thank you!");
            client.Close();
        }
        static void Main(string[] args)
        {
            Console.Title = "File uploader server";
            var listener = new TcpListener(IPAddress.Any, 1308);
            listener.Start(10);
            
            while (true)
            {
                var client = listener.AcceptTcpClient();
                Serve(client);                
            }
        }        
    }
}
1là tham số cần truyền từ luồng chính sang phương thức ở luồng phụ. Phương thức Callback phải có tham số kiểu
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
    class Program
    {
        static readonly string _home = @"E:\TEMP";
        static void Serve(TcpClient client)
        {
            
            var nsStream = client.GetStream();
            var reader = new BinaryReader(nsStream);
            var fileNameLength = reader.ReadInt32();
            var fileDataLength = reader.ReadInt64();
            var fileNameBytes = reader.ReadBytes(fileNameLength);
            var fileName = Encoding.UTF8.GetString(fileNameBytes);
            Console.WriteLine($"File to receive: {fileName}");
            Console.WriteLine($"Bytes to receive: {fileDataLength}");
            var path = Path.Combine(_home, fileName);
            var fStream = File.OpenWrite(path);
            var length = 0L;
            var size = 512;
            var buffer = new byte[size];
            while (length < fileDataLength)
            {
                var count = nsStream.Read(buffer, 0, size);
                fStream.Write(buffer, 0, count);
                length += count;
            }
            Console.WriteLine($"File saved as: {path}");
            Console.WriteLine($"Bytes received: {fStream.Length}");
            Console.WriteLine("-----------");
            fStream.Close();
            var writer = new StreamWriter(nsStream) { AutoFlush = true };
            writer.WriteLine("200 OK, Thank you!");
            client.Close();
        }
        static void Main(string[] args)
        {
            Console.Title = "File uploader server";
            var listener = new TcpListener(IPAddress.Any, 1308);
            listener.Start(10);
            
            while (true)
            {
                var client = listener.AcceptTcpClient();
                Serve(client);                
            }
        }        
    }
}
3, là nơi chứa biến cần truyền từ luồng chính sang

Lớp ThreadPool phù hợp nhất với các công việc dạng fire-and-forget, nghĩa là không cần quan tâm đến kết quả trả về của phương thức

Use BackgroundWorker

Chúng ta viết lại mã của máy chủ để sử dụng lớp BackgroundWorker

using System.ComponentModel;
using System.Threading;
...
static void Main(string[] args)
{
    Console.Title = "File uploader server";
    var listener = new TcpListener(IPAddress.Any, 1308);
    listener.Start(10);
    while (true)
    {
        var client = listener.AcceptTcpClient();
        //Serve(client);
        //ThreadPool.QueueUserWorkItem(Callback, client);
        var worker = new BackgroundWorker();
        worker.DoWork += Worker_DoWork;
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        worker.RunWorkerAsync(client);
    }
}
private static void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{            
    Console.WriteLine($"Thread execution completed: {e.Result}");
}
private static void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    var client = e.Argument as TcpClient;
    Console.WriteLine($"Starting a new thread: {Thread.CurrentThread.ManagedThreadId}");
    Serve(client);
    e.Result = Thread.CurrentThread.ManagedThreadId;
}

Chủ đề php
Chủ đề php
Kết quả chạy chương trình với hai client cùng upload file, server sử dụng BackgroundWorker

Lớp BackgroundWorker được xây dựng theo mô hình hướng sự kiện (hướng sự kiện). Theo đó, các phương thức thực thi trong luồng mới được viết theo kiểu phương thức xử lý sự kiện

Sự kiện DoWork sẽ được kích hoạt khi chúng ta gọi phương thức RunWorkerAsync. Sự kiện RunWorkerCompleted được kích hoạt khi hoàn thành việc thực thi toàn bộ mã trên luồng phụ. Ngoài ra, còn có sự kiện ProgressChanged được kích hoạt mỗi khi có sự thay đổi giá trị của một biến bất kỳ trên luồng phụ

Tất cả các phương thức gán cho sự kiện DoWork sẽ được thực thi trong luồng phụ

BackgroundWorker cho phép truyền tham số cho phương thức thực thi ở luồng khác khi gọi

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
    class Program
    {
        static readonly string _home = @"E:\TEMP";
        static void Serve(TcpClient client)
        {
            
            var nsStream = client.GetStream();
            var reader = new BinaryReader(nsStream);
            var fileNameLength = reader.ReadInt32();
            var fileDataLength = reader.ReadInt64();
            var fileNameBytes = reader.ReadBytes(fileNameLength);
            var fileName = Encoding.UTF8.GetString(fileNameBytes);
            Console.WriteLine($"File to receive: {fileName}");
            Console.WriteLine($"Bytes to receive: {fileDataLength}");
            var path = Path.Combine(_home, fileName);
            var fStream = File.OpenWrite(path);
            var length = 0L;
            var size = 512;
            var buffer = new byte[size];
            while (length < fileDataLength)
            {
                var count = nsStream.Read(buffer, 0, size);
                fStream.Write(buffer, 0, count);
                length += count;
            }
            Console.WriteLine($"File saved as: {path}");
            Console.WriteLine($"Bytes received: {fStream.Length}");
            Console.WriteLine("-----------");
            fStream.Close();
            var writer = new StreamWriter(nsStream) { AutoFlush = true };
            writer.WriteLine("200 OK, Thank you!");
            client.Close();
        }
        static void Main(string[] args)
        {
            Console.Title = "File uploader server";
            var listener = new TcpListener(IPAddress.Any, 1308);
            listener.Start(10);
            
            while (true)
            {
                var client = listener.AcceptTcpClient();
                Serve(client);                
            }
        }        
    }
}
4. Giá trị này được lấy ra trong thân phương thức (thực thi ở luồng phụ) bằng lệnh
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
    class Program
    {
        static readonly string _home = @"E:\TEMP";
        static void Serve(TcpClient client)
        {
            
            var nsStream = client.GetStream();
            var reader = new BinaryReader(nsStream);
            var fileNameLength = reader.ReadInt32();
            var fileDataLength = reader.ReadInt64();
            var fileNameBytes = reader.ReadBytes(fileNameLength);
            var fileName = Encoding.UTF8.GetString(fileNameBytes);
            Console.WriteLine($"File to receive: {fileName}");
            Console.WriteLine($"Bytes to receive: {fileDataLength}");
            var path = Path.Combine(_home, fileName);
            var fStream = File.OpenWrite(path);
            var length = 0L;
            var size = 512;
            var buffer = new byte[size];
            while (length < fileDataLength)
            {
                var count = nsStream.Read(buffer, 0, size);
                fStream.Write(buffer, 0, count);
                length += count;
            }
            Console.WriteLine($"File saved as: {path}");
            Console.WriteLine($"Bytes received: {fStream.Length}");
            Console.WriteLine("-----------");
            fStream.Close();
            var writer = new StreamWriter(nsStream) { AutoFlush = true };
            writer.WriteLine("200 OK, Thank you!");
            client.Close();
        }
        static void Main(string[] args)
        {
            Console.Title = "File uploader server";
            var listener = new TcpListener(IPAddress.Any, 1308);
            listener.Start(10);
            
            while (true)
            {
                var client = listener.AcceptTcpClient();
                Serve(client);                
            }
        }        
    }
}
5

Nên sử dụng BackgroundWorker nếu chúng ta muốn dễ dàng lấy kết quả thực hiện phương thức ở luồng phụ, hoặc muốn theo dõi sự thay đổi của biến trong luồng phụ. BackgroundWorker cũng rất phù hợp khi xây dựng client với công nghệ windows form

Use Layer Thread

Chúng ta viết lại mã của máy chủ để sử dụng lớp Chủ đề

using System.Threading;
...
static void Main(string[] args)
{
    Console.Title = "File uploader server";
    var listener = new TcpListener(IPAddress.Any, 1308);
    listener.Start(10);
    while (true)
    {
        var client = listener.AcceptTcpClient();
        //Serve(client);
        //ThreadPool.QueueUserWorkItem(Callback, client);
        //var worker = new BackgroundWorker();
        //worker.DoWork += Worker_DoWork;
        //worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        //worker.RunWorkerAsync(client);
        var thread = new Thread(Start);
        thread.Start(client);
    }
}
private static void Start(object state)
{
    var client = state as TcpClient;
    Console.WriteLine($"Starting a new thread: {Thread.CurrentThread.ManagedThreadId}");
    Serve(client);
}

Chủ đề php
Chủ đề php

Chủ đề là lớp cơ bản nhất được sử dụng để thiết lập luồng đa luồng trong. MẠNG LƯỚI. Đây là lớp linh hoạt nhất nhưng cũng phức tạp nhất khi sử dụng. Chỉ nên sử dụng lớp Chủ đề nếu có những yêu cầu đặc biệt về xử lý luồng

Đối với những yêu cầu đơn giản (như bài toán truyền tải tệp của chúng ta), việc sử dụng Thread, BackgroundWorker hay ThreadPool không có sự khác biệt lớn

Kết luận

Trong bài học này, chúng tôi đã cùng xem xét khái niệm luồng thực thi và một số kỹ thuật thiết lập trình đa luồng trong. Nền tảng NET

Các kỹ thuật này rất quan trọng khi xây dựng thành phần máy chủ. Chúng giúp server đồng thời xử lý nhiều kết nối, server cùng lúc nhiều client. Qua đó tăng hiệu suất của máy chủ

Các kỹ thuật này cũng đóng vai trò quan trọng khi xây dựng ứng dụng khách với giao diện đồ họa. Họ giúp chương trình thân thiện với người dùng không treo ứng dụng khi thực hiện các tác vụ kéo dài