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

C#優(yōu)雅實(shí)現(xiàn)HttpClient封裝的具體方案

 更新時(shí)間:2025年12月19日 08:47:10   作者:淺嘗輒止;  
在 C# 開(kāi)發(fā)中,HttpClient 是發(fā)送 HTTP 請(qǐng)求的核心組件,但直接 new 實(shí)例的方式存在性能差、連接泄漏等問(wèn)題,本文將分享靜態(tài)單例 + 通用方法封裝的最優(yōu)實(shí)踐,需要的朋友可以參考下

引言

在 C# 開(kāi)發(fā)中,HttpClient 是發(fā)送 HTTP 請(qǐng)求的核心組件,但直接 new 實(shí)例的方式存在性能差、連接泄漏等問(wèn)題。本文將分享「靜態(tài)單例 + 通用方法封裝」的最優(yōu)實(shí)踐,同時(shí)補(bǔ)充 .NET Core/.NET 5+ 推薦的 IHttpClientFactory 實(shí)現(xiàn)方案,提供可直接復(fù)制復(fù)用的工具類(lèi)代碼,適配不同 .NET 版本場(chǎng)景。

本文核心價(jià)值:

  • 解決 HttpClient 頻繁創(chuàng)建導(dǎo)致的性能問(wèn)題
  • 提供 GET/POST(JSON/表單) 通用封裝方法
  • 適配 .NET Framework 和 .NET Core 多場(chǎng)景
  • 包含完整異常處理、請(qǐng)求配置最佳實(shí)踐

一、核心前提:為什么不建議每次 new HttpClient?

很多開(kāi)發(fā)者習(xí)慣在每次請(qǐng)求時(shí) new HttpClient,這種寫(xiě)法存在明顯缺陷:

  1. 創(chuàng)建成本高:每次 new 會(huì)初始化新的 HttpMessageHandler(含連接池、SSL 上下文等重量級(jí)組件)
  2. 連接池?zé)o法復(fù)用:導(dǎo)致 TCP 連接頻繁創(chuàng)建/銷(xiāo)毀,增加網(wǎng)絡(luò)開(kāi)銷(xiāo),甚至引發(fā)端口耗盡
  3. 資源泄漏風(fēng)險(xiǎn):未正確 Dispose 會(huì)導(dǎo)致 socket 連接長(zhǎng)期占用(.NET Framework 中更明顯)
  4. DNS 緩存問(wèn)題:?jiǎn)卫?HttpClient 可能緩存 DNS,導(dǎo)致域名解析變更后無(wú)法生效(.NET Core 前版本)

核心原則:HttpClient 應(yīng)復(fù)用而非頻繁創(chuàng)建,基于單例或工廠模式管理實(shí)例生命周期。

二、基礎(chǔ)方案:靜態(tài)單例 + 通用方法封裝(.NET Framework 適用)

適合 .NET Framework 項(xiàng)目,通過(guò)靜態(tài)工具類(lèi)封裝 HttpClient 單例,提供 GET/POST 通用方法,統(tǒng)一處理請(qǐng)求頭、超時(shí)、異常等邏輯。

2.1 完整工具類(lèi)代碼

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

/// 
public static class HttpClientHelper
{
    // 全局單例 HttpClient(核心:復(fù)用連接池)
    private static readonly HttpClient _httpClient;

    /// 
    static HttpClientHelper()
    {
        // 1. 配置連接池、超時(shí)等核心參數(shù)
        var handler = new HttpClientHandler
        {
            // 限制每個(gè)服務(wù)器的最大并發(fā)連接數(shù)(根據(jù)目標(biāo)服務(wù)能力調(diào)整,建議 50-200)
            MaxConnectionsPerServer = 100,
            // 允許自動(dòng)重定向(根據(jù)業(yè)務(wù)需求調(diào)整)
            AllowAutoRedirect = true,
            // 【測(cè)試環(huán)境專(zhuān)用】忽略 SSL 證書(shū)錯(cuò)誤(生產(chǎn)環(huán)境務(wù)必刪除?。?
            // ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
        };

        // 2. 初始化 HttpClient 實(shí)例
        _httpClient = new HttpClient(handler)
        {
            // 全局默認(rèn)超時(shí)(30秒,避免請(qǐng)求無(wú)限掛起)
            Timeout = TimeSpan.FromSeconds(30)
        };

        // 3. 設(shè)置默認(rèn)請(qǐng)求頭(減少重復(fù)代碼)
        _httpClient.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
        _httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("CSharp-HttpClient-Tool/1.0");
    }

    #region 通用 GET 請(qǐng)求(返回字符串結(jié)果)
    /// 
    /// <param name="url">請(qǐng)求地址(必填)</param>
    /// <param name="headers">自定義請(qǐng)求頭(可選,如 Authorization)</param>
    /// <returns>響應(yīng)內(nèi)容字符串</returns>
    /// <exception cref="ArgumentNullException">url 為空時(shí)拋出</exception>
    /// <exception cref="HttpRequestException">HTTP 請(qǐng)求失敗時(shí)拋出(非 2xx 狀態(tài)碼)</exception>
    public static async Task<string> GetAsync(string url, HeaderDictionary headers = null)
    {
        // 入?yún)⑿r?yàn)
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException(nameof(url), "請(qǐng)求地址不能為空");

        // 構(gòu)建請(qǐng)求消息
        using var request = new HttpRequestMessage(HttpMethod.Get, url);

        // 添加自定義請(qǐng)求頭
        if (headers != null)
        {
            foreach (var header in headers)
            {
                // 嘗試添加到請(qǐng)求頭,失敗則嘗試添加到內(nèi)容頭
                if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value) &&
                    !request.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value) ?? false)
                {
                    throw new InvalidOperationException($"無(wú)法添加請(qǐng)求頭:{header.Key}");
                }
            }
        }

        // 發(fā)送請(qǐng)求(復(fù)用單例 HttpClient)
        using var response = await _httpClient.SendAsync(request);
        // 確保響應(yīng)成功(非 2xx 狀態(tài)碼會(huì)拋 HttpRequestException)
        response.EnsureSuccessStatusCode();

        // 讀取響應(yīng)內(nèi)容
        return await response.Content.ReadAsStringAsync();
    }
    #endregion

    #region 通用 POST 請(qǐng)求(JSON 入?yún)ⅲ?
    /// 
    /// <param name="url">請(qǐng)求地址(必填)</param>
    /// <param name="jsonBody">JSON 字符串(必填)</param>
    /// <param name="headers">自定義請(qǐng)求頭(可選)</param>
    /// <returns>響應(yīng)內(nèi)容字符串</returns>
    /// <exception cref="ArgumentNullException">url 或 jsonBody 為空時(shí)拋出</exception>
    public static async Task<string> PostJsonAsync(string url, string jsonBody, HeaderDictionary headers = null)
    {
        // 入?yún)⑿r?yàn)
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException(nameof(url), "請(qǐng)求地址不能為空");
        if (string.IsNullOrEmpty(jsonBody))
            throw new ArgumentNullException(nameof(jsonBody), "JSON 入?yún)⒉荒転榭?);

        // 構(gòu)建 JSON 內(nèi)容(指定 UTF-8 編碼和 application/json 格式)
        using var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

        // 構(gòu)建請(qǐng)求消息
        using var request = new HttpRequestMessage(HttpMethod.Post, url)
        {
            Content = content
        };

        // 添加自定義請(qǐng)求頭
        if (headers != null)
        {
            foreach (var header in headers)
            {
                if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value) &&
                    !request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value))
                {
                    throw new InvalidOperationException($"無(wú)法添加請(qǐng)求頭:{header.Key}");
                }
            }
        }

        // 發(fā)送請(qǐng)求并處理響應(yīng)
        using var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
    #endregion

    #region 擴(kuò)展:POST 表單請(qǐng)求(鍵值對(duì)入?yún)ⅲ?
    ///     /// <param name="url">請(qǐng)求地址(必填)</param>
    /// <param name="formData">表單數(shù)據(jù)(鍵值對(duì))</param>
    /// <returns>響應(yīng)內(nèi)容字符串</returns>
    public static async Task<string> PostFormAsync(string url, FormUrlEncodedContent formData)
    {
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException(nameof(url), "請(qǐng)求地址不能為空");
        if (formData == null)
            throw new ArgumentNullException(nameof(formData), "表單數(shù)據(jù)不能為空");

        // 直接調(diào)用 PostAsync(簡(jiǎn)化表單請(qǐng)求邏輯)
        using var response = await _httpClient.PostAsync(url, formData);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
    #endregion
}

/// 
public class HeaderDictionary : Dictionary<string, string>
{
    public HeaderDictionary() : base(StringComparer.OrdinalIgnoreCase) { }
}

2.2 使用示例(復(fù)制即運(yùn)行)

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // 示例1:調(diào)用 GET 方法(帶 Authorization 頭)
        await TestGetAsync();

        // 示例2:調(diào)用 POST JSON 方法
        await TestPostJsonAsync();

        // 示例3:調(diào)用 POST 表單方法
        await TestPostFormAsync();
    }

    /// 
    private static async Task TestGetAsync()
    {
        try
        {
            // 自定義請(qǐng)求頭(如 Token 認(rèn)證)
            var headers = new HeaderDictionary
            {
                { "Authorization", "Bearer your_token_here" }
            };

            // 調(diào)用工具類(lèi)方法
            string result = await HttpClientHelper.GetAsync(
                "https://api.example.com/data", headers);

            Console.WriteLine("GET 響應(yīng)結(jié)果:" + result);
        }
        catch (Exception ex)
        {
            Console.WriteLine("GET 請(qǐng)求失?。? + ex.Message);
        }
    }

    /// 
    private static async Task TestPostJsonAsync()
    {
        try
        {
            // 構(gòu)造 JSON 入?yún)?
            string jsonBody = "{\"name\":\"測(cè)試用戶\",\"age\":25}";

            // 調(diào)用工具類(lèi)方法
            string result = await HttpClientHelper.PostJsonAsync(
                "https://api.example.com/submit", jsonBody);

            Console.WriteLine("POST JSON 響應(yīng)結(jié)果:" + result);
        }
        catch (Exception ex)
        {
            Console.WriteLine("POST JSON 請(qǐng)求失?。? + ex.Message);
        }
    }

    /// 
    private static async Task TestPostFormAsync()
    {
        try
        {
            // 構(gòu)造表單數(shù)據(jù)(用戶名密碼登錄)
            var formData = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("username", "admin"),
                new KeyValuePair<string, string>("password", "123456")
            });

            // 調(diào)用工具類(lèi)方法
            string result = await HttpClientHelper.PostFormAsync(
                "https://api.example.com/login", formData);

            Console.WriteLine("POST 表單響應(yīng)結(jié)果:" + result);
        }
        catch (Exception ex)
        {
            Console.WriteLine("POST 表單請(qǐng)求失?。? + ex.Message);
        }
    }
}

三、進(jìn)階方案:IHttpClientFactory 實(shí)現(xiàn)(.NET Core/.NET 5+ 推薦)

對(duì)于 .NET Core/.NET 5+ 項(xiàng)目,官方推薦使用IHttpClientFactory 管理 HttpClient 生命周期,解決了傳統(tǒng)單例的 DNS 緩存問(wèn)題,支持靈活配置和生命周期管理。

3.1 步驟1:注冊(cè)服務(wù)(Program.cs)

// .NET 6+ 極簡(jiǎn)模式(Program.cs)
var builder = WebApplication.CreateBuilder(args);

// 方式1:注冊(cè)命名客戶端(推薦,按業(yè)務(wù)分組配置)
builder.Services.AddHttpClient("DefaultClient", client =>
{
    // 基礎(chǔ)地址(后續(xù)請(qǐng)求可省略域名)
    client.BaseAddress = new Uri("https://api.example.com/");
    // 全局超時(shí)配置
    client.Timeout = TimeSpan.FromSeconds(30);
    // 默認(rèn)請(qǐng)求頭
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
})
// 配置連接池和 Handler 生命周期
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
    MaxConnectionsPerServer = 100, // 連接池最大并發(fā)數(shù)
    AllowAutoRedirect = true
})
// 每 5 分鐘刷新 Handler(解決 DNS 緩存問(wèn)題)
.SetHandlerLifetime(TimeSpan.FromMinutes(5));

// 注冊(cè)自定義服務(wù)(后續(xù)注入使用)
builder.Services.AddScoped<HttpClientService>();

var app = builder.Build();

// 其他中間件配置...

app.Run();

3.2 步驟2:封裝服務(wù)類(lèi)

using System;
using System.Net.Http;
using System.Threading.Tasks;

/// 
public class HttpClientService
{
    private readonly IHttpClientFactory _httpClientFactory;

    // 構(gòu)造函數(shù)注入 IHttpClientFactory
    public HttpClientService(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    /// 
    public async Task<string> GetAsync(string url, HeaderDictionary headers = null)
    {
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException(nameof(url), "請(qǐng)求地址不能為空");

        // 從工廠獲取命名客戶端("DefaultClient" 對(duì)應(yīng)注冊(cè)時(shí)的名稱(chēng))
        var client = _httpClientFactory.CreateClient("DefaultClient");

        using var request = new HttpRequestMessage(HttpMethod.Get, url);

        // 添加自定義請(qǐng)求頭
        if (headers != null)
        {
            foreach (var header in headers)
            {
                request.Headers.TryAddWithoutValidation(header.Key, header.Value);
            }
        }

        // 發(fā)送請(qǐng)求并處理響應(yīng)
        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }

    /// 
    public async Task<string> PostJsonAsync(string url, string jsonBody, HeaderDictionary headers = null)
    {
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException(nameof(url), "請(qǐng)求地址不能為空");
        if (string.IsNullOrEmpty(jsonBody))
            throw new ArgumentNullException(nameof(jsonBody), "JSON 入?yún)⒉荒転榭?);

        var client = _httpClientFactory.CreateClient("DefaultClient");
        using var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
        using var request = new HttpRequestMessage(HttpMethod.Post, url) { Content = content };

        if (headers != null)
        {
            foreach (var header in headers)
            {
                request.Headers.TryAddWithoutValidation(header.Key, header.Value);
            }
        }

        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

// 復(fù)用之前定義的 HeaderDictionary 輔助類(lèi)
public class HeaderDictionary : Dictionary<string, string>
{
    public HeaderDictionary() : base(StringComparer.OrdinalIgnoreCase) { }
}

3.3 使用示例(Web 項(xiàng)目控制器)

using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

/// 
[ApiController]
[Route("api/[controller]")]
public class TestController : ControllerBase
{
    private readonly HttpClientService _httpClientService;

    // 構(gòu)造函數(shù)注入
    public TestController(HttpClientService httpClientService)
    {
        _httpClientService = httpClientService;
    }

    [HttpGet("data")]
    public async Task<IActionResult> GetData()
    {
        try
        {
            // 調(diào)用服務(wù)方法(此處 url 可省略基礎(chǔ)地址,因?yàn)樽?cè)時(shí)配置了 BaseAddress)
            var result = await _httpClientService.GetAsync("data");
            return Ok(result);
        }
        catch (Exception ex)
        {
            return BadRequest($"請(qǐng)求失?。簕ex.Message}");
        }
    }

    [HttpPost("submit")]
    public async Task<IActionResult> SubmitData([FromBody] UserInfo userInfo)
    {
        try
        {
            // 序列化對(duì)象為 JSON(需引用 Newtonsoft.Json 或使用 System.Text.Json)
            string jsonBody = System.Text.Json.JsonSerializer.Serialize(userInfo);
            var result = await _httpClientService.PostJsonAsync("submit", jsonBody);
            return Ok(result);
        }
        catch (Exception ex)
        {
            return BadRequest($"請(qǐng)求失?。簕ex.Message}");
        }
    }
}

// 測(cè)試實(shí)體類(lèi)
public class UserInfo
{
    public string Name { get; set; }
    public int Age { get; set; }
}

四、關(guān)鍵注意事項(xiàng)(避坑指南)

  1. 禁止每次請(qǐng)求 new HttpClient:無(wú)論哪種方案,核心都是復(fù)用實(shí)例,避免重復(fù)創(chuàng)建 HttpMessageHandler
  2. 不要手動(dòng) Dispose 復(fù)用的 HttpClient:Dispose 會(huì)銷(xiāo)毀連接池,導(dǎo)致后續(xù)請(qǐng)求失?。╱sing 語(yǔ)句僅用于 HttpRequestMessage/HttpResponseMessage)
  3. 必須處理非 2xx 狀態(tài)碼EnsureSuccessStatusCode() 會(huì)在非 2xx 時(shí)拋 HttpRequestException,需通過(guò) try-catch 捕獲并處理業(yè)務(wù)邏輯
  4. 合理配置超時(shí):默認(rèn)超時(shí) 100 秒,建議顯式設(shè)置為 30 秒內(nèi)(根據(jù)業(yè)務(wù)場(chǎng)景調(diào)整),避免請(qǐng)求長(zhǎng)期掛起
  5. 限制連接池并發(fā)數(shù)MaxConnectionsPerServer 建議設(shè)置為 50-200,避免壓垮目標(biāo)服務(wù)器
  6. DNS 緩存問(wèn)題處理:.NET Core 前版本使用靜態(tài)單例時(shí),若目標(biāo)域名解析變更,需手動(dòng)刷新 HttpMessageHandler;.NET Core/.NET 5+ 直接使用 IHttpClientFactory 即可
  7. 生產(chǎn)環(huán)境禁用 SSL 證書(shū)忽略:測(cè)試環(huán)境可臨時(shí)開(kāi)啟 ServerCertificateCustomValidationCallback,生產(chǎn)環(huán)境務(wù)必刪除,避免安全風(fēng)險(xiǎn)

五、方案選型建議

項(xiàng)目類(lèi)型推薦方案優(yōu)勢(shì)
.NET Framework(4.x)靜態(tài)單例 + 通用方法封裝簡(jiǎn)單易用,無(wú)需依賴(lài)注入,適配舊項(xiàng)目
.NET Core/.NET 5+(Web/控制臺(tái))IHttpClientFactory + 注入式服務(wù)自動(dòng)管理生命周期,解決 DNS 緩存問(wèn)題,支持靈活配置
簡(jiǎn)單控制臺(tái)/工具類(lèi)項(xiàng)目靜態(tài)單例 HttpClient代碼簡(jiǎn)潔,無(wú)額外依賴(lài)

六、總結(jié)

本文提供的兩種 HttpClient 封裝方案,核心都是「復(fù)用實(shí)例、統(tǒng)一配置、簡(jiǎn)化調(diào)用」:

  • 基礎(chǔ)方案適配 .NET Framework 舊項(xiàng)目,復(fù)制代碼即可直接使用;
  • 進(jìn)階方案適配 .NET Core 新項(xiàng)目,符合官方最佳實(shí)踐,擴(kuò)展性更強(qiáng)。

通過(guò)封裝,不僅能提升請(qǐng)求性能(連接池復(fù)用),還能統(tǒng)一處理異常、請(qǐng)求頭、超時(shí)等邏輯,大幅降低重復(fù)編碼成本。如果需要擴(kuò)展其他請(qǐng)求類(lèi)型(如 PUT/DELETE),可參考文中方法直接補(bǔ)充即可。

以上就是C#優(yōu)雅實(shí)現(xiàn)HttpClient封裝的具體方案的詳細(xì)內(nèi)容,更多關(guān)于C# HttpClient封裝的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#實(shí)現(xiàn)對(duì)文件進(jìn)行加密解密的方法

    C#實(shí)現(xiàn)對(duì)文件進(jìn)行加密解密的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)對(duì)文件進(jìn)行加密解密的方法,涉及C#加密與解密的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-04-04
  • 基于C#中XmlWriter寫(xiě)入Xml的深入分析

    基于C#中XmlWriter寫(xiě)入Xml的深入分析

    本篇文章是對(duì)C#中XmlWriter寫(xiě)入Xml進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C#多線程系列之線程完成數(shù)

    C#多線程系列之線程完成數(shù)

    本文詳細(xì)講解了C#多線程中的線程完成數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • C# 寫(xiě)入XML文檔三種方法詳細(xì)介紹

    C# 寫(xiě)入XML文檔三種方法詳細(xì)介紹

    如何使用LINQ to XML對(duì)XML進(jìn)行操作,我們分別用這三個(gè)類(lèi)將同樣的xml內(nèi)容寫(xiě)入文檔,需要了解的朋友可以參考下
    2012-12-12
  • C# 內(nèi)部類(lèi)與Lambda表達(dá)式用法詳解

    C# 內(nèi)部類(lèi)與Lambda表達(dá)式用法詳解

    Lambda表達(dá)式是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對(duì)應(yīng)于其中的lambda抽象,是一個(gè)匿名函數(shù),即沒(méi)有函數(shù)名的函數(shù);內(nèi)部類(lèi)是將一個(gè)類(lèi)定義在另一個(gè)給類(lèi)里面或者方法里面,這樣的類(lèi)就被稱(chēng)為內(nèi)部類(lèi)
    2021-10-10
  • C#讀寫(xiě)config配置文件的方法

    C#讀寫(xiě)config配置文件的方法

    下面小編就為大家?guī)?lái)一篇C#讀寫(xiě)config配置文件的方法。小編覺(jué)的挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • WinForm中實(shí)現(xiàn)數(shù)據(jù)的異步加載與進(jìn)度可視化

    WinForm中實(shí)現(xiàn)數(shù)據(jù)的異步加載與進(jìn)度可視化

    在開(kāi)發(fā)WinForm應(yīng)用程序時(shí),經(jīng)常會(huì)遇到需要加載大量數(shù)據(jù)的場(chǎng)景,比如讀取文件、查詢數(shù)據(jù)庫(kù)或調(diào)用遠(yuǎn)程接口,如果這些操作直接在主線程中執(zhí)行,UI界面就會(huì)出現(xiàn)假死現(xiàn)象,所以本文將介紹如何使用.NET提供的BackgroundWorker組件,實(shí)現(xiàn)數(shù)據(jù)的異步加載與進(jìn)度可視化
    2025-09-09
  • C#關(guān)于Task.Yeild()函數(shù)的討論

    C#關(guān)于Task.Yeild()函數(shù)的討論

    這篇文章主要介紹了C#中關(guān)于Task.Yeild()函數(shù)的相關(guān)資料,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C# Random類(lèi)的正確應(yīng)用方法

    C# Random類(lèi)的正確應(yīng)用方法

    這篇文章主要介紹了C# Random類(lèi)的正確應(yīng)用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 為IObservable實(shí)現(xiàn)自己的運(yùn)算符(詳解)

    為IObservable實(shí)現(xiàn)自己的運(yùn)算符(詳解)

    下面小編就為大家?guī)?lái)一篇為IObservable實(shí)現(xiàn)自己的運(yùn)算符(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05

最新評(píng)論

甘孜县| 林周县| 德州市| 嵊州市| 武宣县| 易门县| 久治县| 中西区| 尚义县| 巴楚县| 佛冈县| 莱西市| 襄城县| 大安市| 班戈县| 彭山县| 广东省| 淮南市| 乌鲁木齐县| 连江县| 德清县| 航空| 大厂| 渑池县| 屯门区| 株洲县| 张家川| 兴山县| 沙雅县| 南京市| 藁城市| 西林县| 海伦市| 兴安县| 库车县| 大安市| 开封市| 介休市| 临湘市| 毕节市| 卓资县|