最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用.NET8實現(xiàn)一個完整的串口通訊工具類

 更新時間:2025年08月26日 09:02:51   作者:code_shenbing  
串口通信在工業(yè)控制、物聯(lián)網(wǎng)設(shè)備、嵌入式系統(tǒng)和自動化領(lǐng)域仍然廣泛應(yīng)用,.NET 8 提供了強(qiáng)大的 System.IO.Ports命名空間,使得實現(xiàn)串口通信變得簡單高效,本文將詳細(xì)介紹如何使用 .NET 8 實現(xiàn)一個功能完整的串口通信工具類,需要的朋友可以參考下

引言

串口通信(Serial Communication)在工業(yè)控制、物聯(lián)網(wǎng)設(shè)備、嵌入式系統(tǒng)和自動化領(lǐng)域仍然廣泛應(yīng)用。.NET 8 提供了強(qiáng)大的 System.IO.Ports命名空間,使得實現(xiàn)串口通信變得簡單高效。本文將詳細(xì)介紹如何使用 .NET 8 實現(xiàn)一個功能完整的串口通信工具類,包含配置管理、數(shù)據(jù)收發(fā)、事件處理和錯誤處理等功能。

1. 串口通信工具類設(shè)計

首先,我們設(shè)計一個 SerialPortTool類,封裝所有串口操作:

using System;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
 
public class SerialPortTool : IDisposable
{
    private SerialPort _serialPort;
    private CancellationTokenSource _cancellationTokenSource;
    private bool _isOpen = false;
    
    // 事件定義
    public event EventHandler<string> PortOpened;
    public event EventHandler<string> PortClosed;
    public event EventHandler<byte[]> DataReceived;
    public event EventHandler<string> MessageReceived;
    public event EventHandler<Exception> ErrorOccurred;
    
    // 配置屬性
    public string PortName { get; private set; }
    public int BaudRate { get; private set; }
    public Parity Parity { get; private set; }
    public int DataBits { get; private set; }
    public StopBits StopBits { get; private set; }
    public Handshake Handshake { get; private set; }
    public int ReadTimeout { get; private set; }
    public int WriteTimeout { get; private set; }
    
    public bool IsOpen => _isOpen && _serialPort?.IsOpen == true;
    
    public SerialPortTool(string portName, int baudRate = 9600, 
                         Parity parity = Parity.None, int dataBits = 8, 
                         StopBits stopBits = StopBits.One, 
                         Handshake handshake = Handshake.None,
                         int readTimeout = 1000, int writeTimeout = 1000)
    {
        PortName = portName;
        BaudRate = baudRate;
        Parity = parity;
        DataBits = dataBits;
        StopBits = stopBits;
        Handshake = handshake;
        ReadTimeout = readTimeout;
        WriteTimeout = writeTimeout;
        
        _cancellationTokenSource = new CancellationTokenSource();
    }
    
    // 其余實現(xiàn)將在下面展開...
}

2. 實現(xiàn)串口打開和關(guān)閉

2.1 打開串口

public bool Open()
{
    if (IsOpen)
        return true;
 
    try
    {
        _serialPort = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits)
        {
            Handshake = Handshake,
            ReadTimeout = ReadTimeout,
            WriteTimeout = WriteTimeout
        };
        
        _serialPort.Open();
        _isOpen = true;
        
        // 啟動數(shù)據(jù)接收后臺任務(wù)
        _ = Task.Run(() => ReceiveDataAsync(_cancellationTokenSource.Token));
        
        PortOpened?.Invoke(this, $"串口 {PortName} 已打開");
        return true;
    }
    catch (Exception ex)
    {
        ErrorOccurred?.Invoke(this, ex);
        Close();
        return false;
    }
}

2.2 關(guān)閉串口

public void Close()
{
    try
    {
        _cancellationTokenSource.Cancel();
        _serialPort?.Close();
        _serialPort?.Dispose();
        _serialPort = null;
        _isOpen = false;
        
        PortClosed?.Invoke(this, $"串口 {PortName} 已關(guān)閉");
    }
    catch (Exception ex)
    {
        ErrorOccurred?.Invoke(this, ex);
    }
}

3. 實現(xiàn)數(shù)據(jù)發(fā)送和接收

3.1 發(fā)送數(shù)據(jù)

public bool Send(byte[] data)
{
    if (!IsOpen)
        return false;
 
    try
    {
        _serialPort.Write(data, 0, data.Length);
        return true;
    }
    catch (Exception ex)
    {
        ErrorOccurred?.Invoke(this, ex);
        Close();
        return false;
    }
}
 
public bool SendString(string message, Encoding encoding = null)
{
    encoding ??= Encoding.UTF8;
    byte[] data = encoding.GetBytes(message);
    return Send(data);
}
 
public async Task<bool> SendAsync(byte[] data)
{
    if (!IsOpen)
        return false;
 
    try
    {
        await _serialPort.BaseStream.WriteAsync(data, 0, data.Length);
        return true;
    }
    catch (Exception ex)
    {
        ErrorOccurred?.Invoke(this, ex);
        Close();
        return false;
    }
}
 
public async Task<bool> SendStringAsync(string message, Encoding encoding = null)
{
    encoding ??= Encoding.UTF8;
    byte[] data = encoding.GetBytes(message);
    return await SendAsync(data);
}

3.2 接收數(shù)據(jù)(后臺任務(wù))

private async Task ReceiveDataAsync(CancellationToken cancellationToken)
{
    byte[] buffer = new byte[4096];
    
    while (!cancellationToken.IsCancellationRequested && IsOpen)
    {
        try
        {
            // 異步讀取數(shù)據(jù)
            int bytesRead = await _serialPort.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
            
            if (bytesRead > 0)
            {
                // 復(fù)制接收到的數(shù)據(jù)
                byte[] receivedData = new byte[bytesRead];
                Array.Copy(buffer, receivedData, bytesRead);
                
                // 觸發(fā)數(shù)據(jù)接收事件
                DataReceived?.Invoke(this, receivedData);
                
                // 轉(zhuǎn)換為字符串并觸發(fā)消息接收事件
                string message = Encoding.UTF8.GetString(receivedData);
                MessageReceived?.Invoke(this, message);
            }
        }
        catch (OperationCanceledException)
        {
            // 任務(wù)被取消,正常退出
            break;
        }
        catch (TimeoutException)
        {
            // 讀取超時,繼續(xù)等待
        }
        catch (Exception ex)
        {
            if (IsOpen) // 只在串口打開時報告錯誤
            {
                ErrorOccurred?.Invoke(this, ex);
            }
            break;
        }
    }
}

4. 完整工具類實現(xiàn)

下面是完整的 SerialPortTool類實現(xiàn):

using System;
using System.IO.Ports;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
public class SerialPortTool : IDisposable
{
    private SerialPort _serialPort;
    private CancellationTokenSource _cancellationTokenSource;
    private bool _isOpen = false;
    
    // 事件定義
    public event EventHandler<string> PortOpened;
    public event EventHandler<string> PortClosed;
    public event EventHandler<byte[]> DataReceived;
    public event EventHandler<string> MessageReceived;
    public event EventHandler<Exception> ErrorOccurred;
    
    // 配置屬性
    public string PortName { get; private set; }
    public int BaudRate { get; private set; }
    public Parity Parity { get; private set; }
    public int DataBits { get; private set; }
    public StopBits StopBits { get; private set; }
    public Handshake Handshake { get; private set; }
    public int ReadTimeout { get; private set; }
    public int WriteTimeout { get; private set; }
    
    public bool IsOpen => _isOpen && _serialPort?.IsOpen == true;
    
    public SerialPortTool(string portName, int baudRate = 9600, 
                         Parity parity = Parity.None, int dataBits = 8, 
                         StopBits stopBits = StopBits.One, 
                         Handshake handshake = Handshake.None,
                         int readTimeout = 1000, int writeTimeout = 1000)
    {
        PortName = portName;
        BaudRate = baudRate;
        Parity = parity;
        DataBits = dataBits;
        StopBits = stopBits;
        Handshake = handshake;
        ReadTimeout = readTimeout;
        WriteTimeout = writeTimeout;
        
        _cancellationTokenSource = new CancellationTokenSource();
    }
    
    public bool Open()
    {
        if (IsOpen)
            return true;
 
        try
        {
            _serialPort = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits)
            {
                Handshake = Handshake,
                ReadTimeout = ReadTimeout,
                WriteTimeout = WriteTimeout
            };
            
            _serialPort.Open();
            _isOpen = true;
            
            // 啟動數(shù)據(jù)接收后臺任務(wù)
            _ = Task.Run(() => ReceiveDataAsync(_cancellationTokenSource.Token));
            
            PortOpened?.Invoke(this, $"串口 {PortName} 已打開");
            return true;
        }
        catch (Exception ex)
        {
            ErrorOccurred?.Invoke(this, ex);
            Close();
            return false;
        }
    }
    
    public void Close()
    {
        try
        {
            _cancellationTokenSource.Cancel();
            _serialPort?.Close();
            _serialPort?.Dispose();
            _serialPort = null;
            _isOpen = false;
            
            PortClosed?.Invoke(this, $"串口 {PortName} 已關(guān)閉");
        }
        catch (Exception ex)
        {
            ErrorOccurred?.Invoke(this, ex);
        }
    }
    
    public bool Send(byte[] data)
    {
        if (!IsOpen)
            return false;
 
        try
        {
            _serialPort.Write(data, 0, data.Length);
            return true;
        }
        catch (Exception ex)
        {
            ErrorOccurred?.Invoke(this, ex);
            Close();
            return false;
        }
    }
    
    public bool SendString(string message, Encoding encoding = null)
    {
        encoding ??= Encoding.UTF8;
        byte[] data = encoding.GetBytes(message);
        return Send(data);
    }
    
    public async Task<bool> SendAsync(byte[] data)
    {
        if (!IsOpen)
            return false;
 
        try
        {
            await _serialPort.BaseStream.WriteAsync(data, 0, data.Length);
            return true;
        }
        catch (Exception ex)
        {
            ErrorOccurred?.Invoke(this, ex);
            Close();
            return false;
        }
    }
    
    public async Task<bool> SendStringAsync(string message, Encoding encoding = null)
    {
        encoding ??= Encoding.UTF8;
        byte[] data = encoding.GetBytes(message);
        return await SendAsync(data);
    }
    
    private async Task ReceiveDataAsync(CancellationToken cancellationToken)
    {
        byte[] buffer = new byte[4096];
        
        while (!cancellationToken.IsCancellationRequested && IsOpen)
        {
            try
            {
                int bytesRead = await _serialPort.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                
                if (bytesRead > 0)
                {
                    byte[] receivedData = new byte[bytesRead];
                    Array.Copy(buffer, receivedData, bytesRead);
                    
                    DataReceived?.Invoke(this, receivedData);
                    
                    string message = Encoding.UTF8.GetString(receivedData);
                    MessageReceived?.Invoke(this, message);
                }
            }
            catch (OperationCanceledException)
            {
                break;
            }
            catch (TimeoutException)
            {
                // 超時是正常情況,繼續(xù)等待
            }
            catch (Exception ex)
            {
                if (IsOpen)
                {
                    ErrorOccurred?.Invoke(this, ex);
                }
                break;
            }
        }
    }
    
    #region IDisposable Implementation
    private bool _disposed = false;
 
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                Close();
                _cancellationTokenSource?.Dispose();
            }
            _disposed = true;
        }
    }
 
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

5. 使用示例

下面是如何使用串口通信工具類的示例:

class Program
{
    static async Task Main(string[] args)
    {
        // 獲取可用串口列表
        string[] ports = SerialPort.GetPortNames();
        Console.WriteLine("可用串口:");
        foreach (string port in ports)
        {
            Console.WriteLine(port);
        }
        
        if (ports.Length == 0)
        {
            Console.WriteLine("沒有找到可用串口");
            return;
        }
        
        // 使用第一個可用串口
        string selectedPort = ports[0];
        
        using var serialTool = new SerialPortTool(
            portName: selectedPort,
            baudRate: 115200,
            parity: Parity.None,
            dataBits: 8,
            stopBits: StopBits.One
        );
        
        // 訂閱事件
        serialTool.PortOpened += (sender, message) => Console.WriteLine(message);
        serialTool.PortClosed += (sender, message) => Console.WriteLine(message);
        
        serialTool.DataReceived += (sender, data) => 
        {
            Console.WriteLine($"收到字節(jié)數(shù)據(jù): {BitConverter.ToString(data)}");
        };
        
        serialTool.MessageReceived += (sender, message) => 
        {
            Console.WriteLine($"收到消息: {message}");
        };
        
        serialTool.ErrorOccurred += (sender, ex) => 
        {
            Console.WriteLine($"發(fā)生錯誤: {ex.Message}");
        };
        
        // 打開串口
        if (serialTool.Open())
        {
            Console.WriteLine("按 'S' 發(fā)送字符串,按 'B' 發(fā)送字節(jié)數(shù)據(jù),按 'Q' 退出");
            
            while (true)
            {
                var key = Console.ReadKey(intercept: true).Key;
                
                if (key == ConsoleKey.S)
                {
                    Console.Write("輸入要發(fā)送的字符串: ");
                    string message = Console.ReadLine();
                    serialTool.SendString(message);
                }
                else if (key == ConsoleKey.B)
                {
                    Console.Write("輸入要發(fā)送的十六進(jìn)制字節(jié) (例如: 01 02 AA FF): ");
                    string hexInput = Console.ReadLine();
                    
                    try
                    {
                        byte[] data = ParseHexString(hexInput);
                        serialTool.Send(data);
                        Console.WriteLine($"已發(fā)送: {BitConverter.ToString(data)}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"解析錯誤: {ex.Message}");
                    }
                }
                else if (key == ConsoleKey.Q)
                {
                    break;
                }
            }
            
            // 關(guān)閉串口(using語句也會自動調(diào)用Dispose)
            serialTool.Close();
        }
        else
        {
            Console.WriteLine("串口打開失敗");
        }
    }
    
    private static byte[] ParseHexString(string hex)
    {
        hex = hex.Replace(" ", "").Replace("-", "");
        if (hex.Length % 2 != 0)
            throw new ArgumentException("十六進(jìn)制字符串長度必須為偶數(shù)");
        
        byte[] bytes = new byte[hex.Length / 2];
        for (int i = 0; i < bytes.Length; i++)
        {
            string byteValue = hex.Substring(i * 2, 2);
            bytes[i] = Convert.ToByte(byteValue, 16);
        }
        return bytes;
    }
}

6. 高級功能擴(kuò)展

6.1 添加幀處理功能

對于需要處理特定幀格式的應(yīng)用,可以添加幀處理功能:

public class FramedSerialPortTool : SerialPortTool
{
    private readonly byte[] _frameDelimiter;
    private List<byte> _buffer = new List<byte>();
    
    public FramedSerialPortTool(string portName, byte[] frameDelimiter, 
                               int baudRate = 9600, Parity parity = Parity.None, 
                               int dataBits = 8, StopBits stopBits = StopBits.One, 
                               Handshake handshake = Handshake.None,
                               int readTimeout = 1000, int writeTimeout = 1000)
        : base(portName, baudRate, parity, dataBits, stopBits, handshake, readTimeout, writeTimeout)
    {
        _frameDelimiter = frameDelimiter;
        this.DataReceived += OnRawDataReceived;
    }
    
    public new event EventHandler<byte[]> FrameReceived;
    
    private void OnRawDataReceived(object sender, byte[] data)
    {
        _buffer.AddRange(data);
        ProcessBuffer();
    }
    
    private void ProcessBuffer()
    {
        while (true)
        {
            // 查找?guī)指舴?
            int delimiterIndex = FindDelimiter(_buffer.ToArray(), _frameDelimiter);
            
            if (delimiterIndex == -1)
                break;
                
            // 提取完整幀
            byte[] frameData = new byte[delimiterIndex];
            Array.Copy(_buffer.ToArray(), frameData, delimiterIndex);
            
            // 從緩沖區(qū)中移除已處理的數(shù)據(jù)(包括分隔符)
            _buffer.RemoveRange(0, delimiterIndex + _frameDelimiter.Length);
            
            // 觸發(fā)幀接收事件
            FrameReceived?.Invoke(this, frameData);
        }
    }
    
    private int FindDelimiter(byte[] data, byte[] delimiter)
    {
        for (int i = 0; i <= data.Length - delimiter.Length; i++)
        {
            bool found = true;
            for (int j = 0; j < delimiter.Length; j++)
            {
                if (data[i + j] != delimiter[j])
                {
                    found = false;
                    break;
                }
            }
            if (found)
                return i;
        }
        return -1;
    }
    
    public bool SendFrame(byte[] frameData)
    {
        byte[] framedData = new byte[frameData.Length + _frameDelimiter.Length];
        Array.Copy(frameData, framedData, frameData.Length);
        Array.Copy(_frameDelimiter, 0, framedData, frameData.Length, _frameDelimiter.Length);
        
        return Send(framedData);
    }
    
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            this.DataReceived -= OnRawDataReceived;
        }
        base.Dispose(disposing);
    }
}

6.2 添加自動重連功能

對于需要長時間運行的串口應(yīng)用,可以添加自動重連功能:

public class AutoReconnectSerialPortTool : SerialPortTool
{
    private Timer _reconnectTimer;
    private readonly TimeSpan _reconnectInterval;
    private int _reconnectAttempts = 0;
    private const int MAX_RECONNECT_ATTEMPTS = 10;
    
    public AutoReconnectSerialPortTool(string portName, TimeSpan reconnectInterval,
                                      int baudRate = 9600, Parity parity = Parity.None, 
                                      int dataBits = 8, StopBits stopBits = StopBits.One, 
                                      Handshake handshake = Handshake.None,
                                      int readTimeout = 1000, int writeTimeout = 1000)
        : base(portName, baudRate, parity, dataBits, stopBits, handshake, readTimeout, writeTimeout)
    {
        _reconnectInterval = reconnectInterval;
        this.PortClosed += OnPortClosed;
    }
    
    private void OnPortClosed(object sender, string message)
    {
        if (_reconnectAttempts < MAX_RECONNECT_ATTEMPTS)
        {
            _reconnectTimer = new Timer(AttemptReconnect, null, _reconnectInterval, Timeout.InfiniteTimeSpan);
        }
    }
    
    private void AttemptReconnect(object state)
    {
        _reconnectAttempts++;
        
        if (Open())
        {
            _reconnectAttempts = 0; // 重置重試計數(shù)器
            _reconnectTimer?.Dispose();
            _reconnectTimer = null;
        }
    }
    
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _reconnectTimer?.Dispose();
            this.PortClosed -= OnPortClosed;
        }
        base.Dispose(disposing);
    }
}

7. 串口通信最佳實踐

1.??資源管理??:

  • 始終使用 using語句或手動調(diào)用 Dispose()確保資源釋放
  • 在不再需要時關(guān)閉串口連接

2.??錯誤處理??:

  • 處理所有可能的異常(端口不存在、權(quán)限問題、設(shè)備斷開等)
  • 使用事件機(jī)制通知上層應(yīng)用錯誤發(fā)生

3.線程安全??:

  • 串口事件可能在后臺線程觸發(fā),確保UI操作在正確的線程執(zhí)行
  • 使用同步機(jī)制保護(hù)共享資源

4.??性能優(yōu)化??:

  • 使用異步方法避免阻塞UI線程
  • 合理設(shè)置緩沖區(qū)大小平衡內(nèi)存使用和性能
  • 避免在事件處理中執(zhí)行耗時操作

5.??配置管理??:

  • 保存和加載串口配置(波特率、數(shù)據(jù)位等)
  • 提供配置驗證功能

8. 總結(jié)

本文介紹了如何使用 .NET 8 實現(xiàn)一個功能完整的串口通信工具類,包含以下核心功能:

1.??串口管理??:打開、關(guān)閉和狀態(tài)監(jiān)控

2.??數(shù)據(jù)收發(fā)??:支持同步和異步的字節(jié)數(shù)組和字符串傳輸

3.??事件通知??:提供串口狀態(tài)變化、數(shù)據(jù)接收和錯誤通知

4.??資源管理??:正確實現(xiàn) IDisposable接口

5.??錯誤處理??:健壯的異常處理和錯誤通知機(jī)制

通過這種封裝,我們可以在不同的項目中輕松重用串口通信功能,而無需重復(fù)編寫底層代碼。此外,通過繼承和擴(kuò)展,可以輕松添加如幀處理、自動重連等高級功能。

在工業(yè)自動化、物聯(lián)網(wǎng)設(shè)備通信和嵌入式系統(tǒng)開發(fā)中,這種封裝方式能夠顯著提高開發(fā)效率和代碼質(zhì)量,是開發(fā)串口通信應(yīng)用的理想起點。

以上就是使用.NET8實現(xiàn)一個完整的串口通訊工具類的詳細(xì)內(nèi)容,更多關(guān)于.NET8串口通訊工具類的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • asp.net JSONHelper JSON幫助類

    asp.net JSONHelper JSON幫助類

    asp.net JSONHelper JSON幫助類
    2010-01-01
  • ASP.NET實現(xiàn)級聯(lián)下拉框效果實例講解

    ASP.NET實現(xiàn)級聯(lián)下拉框效果實例講解

    這篇文章主要為大家詳細(xì)介紹了ASP.NET實現(xiàn)級聯(lián)下拉框效果實例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-09-09
  • asp.net JSON 序列化技術(shù)分析

    asp.net JSON 序列化技術(shù)分析

    很多人看到的實例都是通過MS AJAX進(jìn)行PageMethod的調(diào)用,但因為近兩年微軟在做ASP.NET與jQuery方面的合作實驗,我們其實也可以通過jQuery進(jìn)行PageMethod的調(diào)用。
    2010-03-03
  • DataTable類Clone方法與Copy方法的區(qū)別分析

    DataTable類Clone方法與Copy方法的區(qū)別分析

    初學(xué)者可能不清楚DataTable類的Clone及Copy方法的區(qū)別,查msdn,可得到如下結(jié)論
    2013-03-03
  • ZKEACMS for .Net Core深度解析

    ZKEACMS for .Net Core深度解析

    ZKEACMS.Core 是基于 .Net Core MVC 開發(fā)的開源CMS,這篇文章主要為大家深度解析了ZKEACMS for .Net Core,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • asp.net Excel轉(zhuǎn)換為SQL Server的方法

    asp.net Excel轉(zhuǎn)換為SQL Server的方法

    辦公軟件Excel是一種常用的電子表格軟件,在編程項目中有需要將Excel轉(zhuǎn)換為SQL Server數(shù)據(jù)庫的需求,本文對此進(jìn)行一些介紹并給出設(shè)計代碼。
    2009-06-06
  • MAUI使用Maui.Graphics.Controls繪制控件詳解

    MAUI使用Maui.Graphics.Controls繪制控件詳解

    本文詳細(xì)講解了MAUI使用Maui.Graphics.Controls繪制控件的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-02-02
  • .Net中如何將一個實例的內(nèi)存二進(jìn)制內(nèi)容讀出來(超簡單方法)

    .Net中如何將一個實例的內(nèi)存二進(jìn)制內(nèi)容讀出來(超簡單方法)

    這篇文章主要介紹了如何將一個實例的內(nèi)存二進(jìn)制內(nèi)容讀出來(超簡單方法),接下來的內(nèi)容中,我們將利用一個簡單的方法輸出指定實例的字節(jié)序列,并此次分析值類型和引用類型實例在內(nèi)存的布局,需要的朋友可以參考下
    2023-07-07
  • 微信公眾平臺開發(fā)之自定義菜單.Net代碼解析

    微信公眾平臺開發(fā)之自定義菜單.Net代碼解析

    這篇文章主要為大家詳細(xì)解析了微信公眾平臺開發(fā)之自定義菜單.Net代碼,感興趣的小伙伴們可以參考一下
    2016-06-06
  • asp.net 客戶端瀏覽器緩存的Http頭介紹

    asp.net 客戶端瀏覽器緩存的Http頭介紹

    做網(wǎng)站開發(fā)離不開緩存,緩存分好多種:服務(wù)器緩存,第三方緩存,瀏覽器緩存等。其中瀏覽器緩存是代價最小的,因為瀏覽器緩存依賴的是客戶端,而幾乎不耗費服務(wù)器端的資源。
    2009-07-07

最新評論

邳州市| 洛南县| 衡水市| 东阿县| 凯里市| 宁南县| 内黄县| 鄂托克前旗| 孝义市| 拜城县| 洪江市| 龙井市| 额济纳旗| 铁岭县| 申扎县| 哈尔滨市| 阜平县| 雷山县| 龙胜| 雷波县| 寿阳县| 隆昌县| 房产| 龙海市| 宜宾县| 聂拉木县| 尤溪县| 阳山县| 四川省| 浦县| 牟定县| 尚义县| 两当县| 宜宾县| 新余市| 徐州市| 德清县| 尉犁县| 宝兴县| 安泽县| 修文县|