主頁 > .NET開發 > 記一次 .NET 某電商定向爬蟲 記憶體碎片化分析

記一次 .NET 某電商定向爬蟲 記憶體碎片化分析

2021-10-11 17:31:31 .NET開發

一:背景

1. 講故事

上個月有位朋友wx找到我,說他的程式存在記憶體泄漏問題,尋求如何解決? 如下圖所示:

從截圖中可以看出,這位朋友對 windbg 的操作還是有些熟悉的,可能缺乏一定的實操經驗,所以用了幾個命令之后就不知道怎么排查下去了,

既然找到我,那就以我的個人經驗在他的dump上繼續分析尋找罪魁禍首,閑話不多說,上windbg說話,

二:Windbg 分析

1. 真的存在記憶體泄漏嗎?

追這個系列的朋友應該知道,我無數次的用 !address -summary!eeheap -gc 這兩個命令來判斷當前的記憶體泄漏是屬于托管層還是非托管層,


0:000> !address -summary

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    358     7dfc`67f60000 ( 125.986 TB)           98.43%
<unknown>                              1087      203`88b6e000 (   2.014 TB)  99.99%    1.57%
Image                                  1532        0`09f11000 ( 159.066 MB)   0.01%    0.00%
Heap                                    249        0`03453000 (  52.324 MB)   0.00%    0.00%
Stack                                    66        0`01fc0000 (  31.750 MB)   0.00%    0.00%
Other                                    10        0`001d1000 (   1.816 MB)   0.00%    0.00%
TEB                                      22        0`0002c000 ( 176.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_MAPPED                              183      200`00d06000 (   2.000 TB)  99.30%    1.56%
MEM_PRIVATE                            1252        3`8d479000 (  14.207 GB)   0.69%    0.01%
MEM_IMAGE                              1532        0`09f11000 ( 159.066 MB)   0.01%    0.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                358     7dfc`67f60000 ( 125.986 TB)           98.43%
MEM_RESERVE                             749      200`28a9b000 (   2.001 TB)  99.33%    1.56%
MEM_COMMIT                             2218        3`6f5f5000 (  13.740 GB)   0.67%    0.01%

0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00000026DA8DA928
generation 1 starts at 0x00000026DA7FC348
generation 2 starts at 0x00000024C4691000
ephemeral segment allocation context: none
         segment             begin         allocated              size
00000024C4690000  00000024C4691000  00000024D468FF28  0xfffef28(268431144)
00000024EECF0000  00000024EECF1000  00000024FECF0000  0xffff000(268431360)
000000248D6F0000  000000248D6F1000  000000249D6EFEF8  0xfffeef8(268431096)
...
00000026D66D0000  00000026D66D1000  00000026DBA3CA30  0x536ba30(87472688)
Large object heap starts at 0x00000024D4691000
         segment             begin         allocated              size
00000024D4690000  00000024D4691000  00000024DC67C318  0x7feb318(134132504)
00000024E60F0000  00000024E60F1000  00000024EE0637C8  0x7f727c8(133638088)
0000002482140000  0000002482141000  000000248A08F338  0x7f4e338(133489464)
00000024A6770000  00000024A6771000  00000024AE76F6C0  0x7ffe6c0(134211264)
...
000000278E6D0000  000000278E6D1000  000000279635F2D0  0x7c8e2d0(130605776)
00000029233E0000  00000029233E1000  000000292AF672F8  0x7b862f8(129524472)
000000292B3E0000  000000292B3E1000  0000002931A5ED60  0x667dd60(107470176)
000000299B3E0000  000000299B3E1000  00000029A20095B0  0x6c285b0(113411504)
000000281E6D0000  000000281E6D1000  0000002825CD3F58  0x7602f58(123744088)
00000028266D0000  00000028266D1000  000000282D5CAD50  0x6ef9d50(116366672)
000000282E6D0000  000000282E6D1000  0000002833CA0880  0x55cf880(89979008)
00000029A33E0000  00000029A33E1000  00000029A684D300  0x346c300(54969088)
Total Size:              Size: 0x353f96d88 (14293757320) bytes.
------------------------------
GC Heap Size:    Size: 0x353f96d88 (14293757320) bytes.

從輸出看,當前行程占用 MEM_COMMIT=13.7G,托管堆記憶體占用 14293757320 = 13.3G,很明顯這屬于簡單模式的 托管記憶體泄漏,根據經驗,托管堆上可能有什么大物件,這里用 !dumpheap -stat 命令,


0:000> !dumpheap -stat
Statistics:
              MT    Count    TotalSize Class Name
00007ff9ed6ea268  3956842     94964208 System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib],[Serilog.Events.LogEventPropertyValue, Serilog]]
00007ff9ed5e6d28  3842435    166405016 Serilog.Parsing.MessageTemplateToken[]
00007ff9ed5e5e28  3842434    184436832 Serilog.Events.MessageTemplate
00007ff9ecccf090  4011012    203304420 System.Int32[]
00007ff9ed647078  3956849    253238336 Serilog.Events.LogEvent
00007ff9ed6e7b48  3956849    284893128 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[Serilog.Events.LogEventPropertyValue, Serilog]]
00007ff9ed5e74e8  9259598    296307136 Serilog.Parsing.TextToken
00007ff9ed6471b0 12551808    301243392 Serilog.Events.ScalarValue
00007ff9ed6e8308  3956849    729078048 System.Collections.Generic.Dictionary`2+Entry[[System.String, System.Private.CoreLib],[Serilog.Events.LogEventPropertyValue, Serilog]][]
00007ff9eccb1e18 16546412   3987811940 System.String
00000024c3b8faf0    82904   7382993568      Free

我去,托管堆最大的物件居然是 Free,大概占用 7.3G, 這就????了,不按套路出牌哈,為了更好的理解,先來簡要解釋下 free 物件,

2. 簡單解釋 free

其實簡而言之,free物件是被gc標記成已回收的空閑塊但并未提交給作業系統釋放的物件,那怎么去證明呢? 可以先到托管堆上找一個free塊,


0:000> !dumpheap -type Free
         Address               MT     Size
00000024c4691000 00000024c3b8faf0       24 Free
00000024c46a2448 00000024c3b8faf0       24 Free
00000024c46b26d8 00000024c3b8faf0       40 Free
00000024c47e4418 00000024c3b8faf0       40 Free
00000024c4925680 00000024c3b8faf0       40 Free
00000024c49284a8 00000024c3b8faf0       64 Free
00000024c4947a90 00000024c3b8faf0      192 Free
00000024c4951f70 00000024c3b8faf0       48 Free         
000000249d6ea3a8 00000024c3b8faf0      640 Free

  1. 用 !do 命令查看是否標記為free塊

0:000> !do 000000249d6ea3a8
Free Object
Size:        640(0x280) bytes

  1. 用 dc 看一下這個 free 塊的內容,是否有gc回收的痕跡,

0:000> dc 000000249d6ea3a8 000000249d6ea3a8+0x280
00000024`9d6ea3a8  c3b8faf0 00000024 00000268 00000000  ....$...h.......
00000024`9d6ea3b8  9d6ea6d0 00000024 00000000 00000000  ..n.$...........
00000024`9d6ea3c8  ed3ae2b8 00007ff9 9d6ea3a8 00000024  ..:.......n.$...
00000024`9d6ea3d8  00000000 00000000 edcc9118 00007ff9  ................
00000024`9d6ea3e8  00000000 00000000 00000000 00000000  ................
00000024`9d6ea3f8  00000000 00000000 00000000 00000000  ................
00000024`9d6ea408  eeb07a50 00007ff9 9d6ea3c8 00000024  Pz........n.$...
00000024`9d6ea418  00000000 00000000 ef292ee8 00007ff9  ..........).....
00000024`9d6ea428  9d6ea408 00000024 00000000 00000000  ..n.$...........
...
00000024`9d6ea4a8  eeb0a158 00007ff9 9d6ea420 00000024  X....... .n.$...
00000024`9d6ea4b8  00000000 00000000 00000000 00000000  ................
00000024`9d6ea4c8  ef293818 00007ff9 9d6ea4a8 00000024  .8).......n.$...
00000024`9d6ea4d8  00000000 00000000 ee8357e0 00007ff9  .........W......
...
00000024`9d6ea508  eed37b40 00007ff9 00000000 00000000  @{..............
00000024`9d6ea518  00000000 00000000 00000000 00000000  ................
00000024`9d6ea528  c4699b48 00000024 00000000 00000000  H.i.$...........
00000024`9d6ea538  00000000 07000440 00000001 00000000  ....@...........
00000024`9d6ea548  00000000 00000000 00000000 00000000  ................
00000024`9d6ea558  00000000 00000000 ef2af6e0 00007ff9  ..........*.....
00000024`9d6ea568  00000000 00000000 00000000 00000000  ................
00000024`9d6ea578  00000000 00000000 c4699b48 00000024  ........H.i.$...
00000024`9d6ea588  00000000 00000000 00000000 07000400  ................
...
00000024`9d6ea628  ef2afd08                             ..*.

可以看到,這個free塊生前是有一些殘留的內容字符,好了,對 free 塊有基本了解后,接下來我們繼續探究下,

3. 到底是什么阻止了free塊的合并?

按照正常邏輯,大多free塊會在gc回收完之后合并記憶體時,那些被清空后的segment會被作業系統釋放的,但這個dump并沒有,也就說明這里有什么東西阻止了free塊的合并,那到底是什么呢? 有經驗的朋友會說,可以觀察下 gc 的句柄表,命令為 !gchandles -stat


0:000> !gchandles -stat
Statistics:
              MT    Count    TotalSize Class Name
...
00007ff9ed15c0f0     1008        72576 System.Reflection.Emit.DynamicResolver
00007ff9ecbf6618       38       409344 System.Object[]
Total 1784 objects

Handles:
    Strong Handles:       233
    Pinned Handles:       16
    Async Pinned Handles: 18
    Ref Count Handles:    1
    Weak Long Handles:    1327
    Weak Short Handles:   144
    Dependent Handles:    45

從輸出看,這里并沒有什么可疑的地方,那怎么辦呢? 實操經驗多的話,這里還是有一些經驗值得分享的,比如觀察 free 在 heap 上的布局特征,往往就有重大發現,

4. 查看 free 塊的布局特征

為了簡化輸出結果,我把范圍限定到 heap 上某一個 segment 上,比如這里的: 00000029233E0000 000000292AF672F8,所以命令就是 !dumpheap 00000029233E0000 000000292AF672F8


0:000> !dumpheap 00000029233E0000  000000292AF672F8
         Address               MT     Size
00000029233e1000 00000024c3b8faf0  8291896 Free
0000002923bc9638 00007ff9eccb1e18   108448     
0000002923be3dd8 00000024c3b8faf0 29931248 Free
000000292586f4c8 00007ff9eccb1e18   301328     
00000029258b8dd8 00000024c3b8faf0 41384784 Free
0000002928030928 00007ff9eccb1e18   301328     
000000292807a238 00000024c3b8faf0  2542664 Free
00000029282e6e80 00007ff9eccb1e18   108448     
0000002928301620 00000024c3b8faf0 29915032 Free
0000002929f88db8 00007ff9eccb1e18   301328     
0000002929fd26c8 00000024c3b8faf0  2746688 Free
000000292a271008 00007ff9eccb1e18   291304     
000000292a2b81f0 00000024c3b8faf0  1019600 Free
000000292a3b10c0 00007ff9eccb1e18   108448     
000000292a3cb860 00000024c3b8faf0 10601048 Free
000000292ade7ab8 00007ff9eccb1e18   301328     
000000292ae313c8 00000024c3b8faf0   280808 Free
000000292ae75cb0 00007ff9eccb1e18   280854     
000000292aeba5c8 00000024c3b8faf0   416584 Free
000000292af20110 00007ff9eccb1e18   291304     

Statistics:
              MT    Count    TotalSize Class Name
00007ff9eccb1e18       10      2394118 System.String
00000024c3b8faf0       10    127130352      Free
Total 20 objects

真是一看嚇一跳,free 和 object 呈交替狀,這就是為什么free塊不能被合并的真正原因,說實話這種教科書式的 記憶體碎片化 dump,真是可遇不可求,接下來就抽幾個 free 之間的 object 物件,看看到底是被什么參考著導致gc回收不掉,

5. 尋找 object 的參考鏈

要想查看 object 到底被誰參考著,可以用 !gcroot 命令,這里我抽二個看看,


0:000> !gcroot 0000002923bc9638
Thread 1878:
    00000024C39BE4B0 00007FFA4C0B3522 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @ 2922]
        rbp+10: 00000024c39be520
            ->  00000024C48AD6E0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions+<RunAsync>d__4, Microsoft.Extensions.Hosting.Abstractions]]
            ->  00000024C48AD200 Microsoft.Extensions.Hosting.Internal.Host
            ->  00000024C48AC538 Microsoft.Extensions.Logging.Logger`1[[Microsoft.Extensions.Hosting.Internal.Host, Microsoft.Extensions.Hosting]]
            ->  00000024C48AC658 Microsoft.Extensions.Logging.Logger
            ->  00000024C48AC680 Microsoft.Extensions.Logging.LoggerInformation[]
            ->  00000024C48AC6E0 Serilog.Extensions.Logging.SerilogLogger
            ->  00000024C48AC808 Serilog.Core.Logger
            ->  00000024C48AC760 Serilog.Core.Logger
            ->  00000024C47AD468 Serilog.Core.Logger
            ->  00000024C47ABF08 Serilog.Core.Sinks.SafeAggregateSink
            ->  00000024C47ABF20 Serilog.Core.ILogEventSink[]
            ->  00000024C479C548 Serilog.Sinks.Grafana.Loki.LokiSink
            ->  00000024C479C778 Serilog.Sinks.Grafana.Loki.Infrastructure.BoundedQueue`1[[Serilog.Events.LogEvent, Serilog]]
            ->  00000024C479C7B8 System.Collections.Generic.Queue`1[[Serilog.Events.LogEvent, Serilog]]
            ->  00000026E8C1A800 Serilog.Events.LogEvent[]
            ->  00000026148D3308 Serilog.Events.LogEvent
            ->  00000026148D4EF0 Serilog.Events.MessageTemplate
            ->  0000002923BC9638 System.String

Found 1 unique roots (run '!gcroot -all' to see all roots).

0:000> !gcroot 000000292586f4c8
Thread 1878:
    00000024C39BE4B0 00007FFA4C0B3522 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @ 2922]
        rbp+10: 00000024c39be520
            ->  00000024C48AD6E0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions+<RunAsync>d__4, Microsoft.Extensions.Hosting.Abstractions]]
            ->  00000024C48AD200 Microsoft.Extensions.Hosting.Internal.Host
            ->  00000024C48AC538 Microsoft.Extensions.Logging.Logger`1[[Microsoft.Extensions.Hosting.Internal.Host, Microsoft.Extensions.Hosting]]
            ->  00000024C48AC658 Microsoft.Extensions.Logging.Logger
            ->  00000024C48AC680 Microsoft.Extensions.Logging.LoggerInformation[]
            ->  00000024C48AC6E0 Serilog.Extensions.Logging.SerilogLogger
            ->  00000024C48AC808 Serilog.Core.Logger
            ->  00000024C48AC760 Serilog.Core.Logger
            ->  00000024C47AD468 Serilog.Core.Logger
            ->  00000024C47ABF08 Serilog.Core.Sinks.SafeAggregateSink
            ->  00000024C47ABF20 Serilog.Core.ILogEventSink[]
            ->  00000024C479C548 Serilog.Sinks.Grafana.Loki.LokiSink
            ->  00000024C479C778 Serilog.Sinks.Grafana.Loki.Infrastructure.BoundedQueue`1[[Serilog.Events.LogEvent, Serilog]]
            ->  00000024C479C7B8 System.Collections.Generic.Queue`1[[Serilog.Events.LogEvent, Serilog]]
            ->  00000026E8C1A800 Serilog.Events.LogEvent[]
            ->  0000002614BB7AC8 Serilog.Events.LogEvent
            ->  0000002616D3CC40 Serilog.Events.MessageTemplate
            ->  000000292586F4C8 System.String

Found 1 unique roots (run '!gcroot -all' to see all roots).

從參考鏈看,這些 object 都是通過 Serilog 日志組件發送給 Grafana.Loki ,通過對參考鏈物件的追蹤,我發現 System.Collections.Generic.Queue 有重大問題,截圖如下:

對,這個 queue 居然有 395w 的積壓,到底積壓了什么東西,可以用 !wdo 看一下string內容,

看樣子這是一個失敗重試,分析到這里思路大概就清晰了,就是 Grafana.Loki 或者 Serilog 組件出了什么問題,導致日志發送不到 Loki 中或者發送速度過慢,然后不斷的積壓所致,接下來把分析到的這些資訊和朋友做了一個溝通,截圖如下:

三:總結

本次記憶體碎片化的主要原因在于 Serilog 對接 Loki 的程序中產生的395w的queue積壓所致,但我也只能分析到這里了,至于為什么有積壓,這個還得朋友進一步除錯分析,我相信這個問題很快就能得到解決??????

圖片名稱

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/308979.html

標籤:.NET技术

上一篇:Blazor Webassembly多標簽頁實作

下一篇:WPF實作聚光燈效果

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more