.NET Core下使用System.Drawing?


.NET Core是從3.0開始才支持System.Drawing的,在3.0之前我們用的是一個叫SixLabors.ImageSharp.Drawing的第三方的庫來實現.NET Core上的繪圖。當我們的系統升級到.NET Core 3.1之后,我就拋棄掉了SixLabors.ImageSharp.Drawing,使用了微軟官方的System.Drawing,一來可以減少一個依賴包,二來我認為官方的東西應該更穩定可靠,更關鍵的一點是SixLabors.ImageSharp.Drawing一直是beta版……

另外吐槽一下這個SixLabors.ImageSharp.Drawing,版本更迭中經常出現斷層,使得升級它的版本常常需要改代碼,不是什么好用的東西。

切到System.Drawing后,一切運行良好,已有一年多的時間。這里需要提到的一點就是,要在Linux下正常使用System.Drawing需要mono項目的libgdiplus,github地址是:https://github.com/mono/libgdiplus,而mono不算是微軟官方的東西,這么看的話System.Drawing也不夠官方啊。

而最近我們系統出問題了,程序直接崩潰,沒有任何征兆,也無法預測,運行一兩天就會出現。檢查Linux的系統日志,發現如此:

Jan 22 13:22:58 l-test njt.fms[5839]: *** Error in `/usr/bin/dotnet': corrupted size vs. prev_size: 0x00007f4a80030c90 ***
Jan 22 13:22:58 l-test njt.fms[5839]: ======= Backtrace: =========
Jan 22 13:22:58 l-test njt.fms[5839]: /lib64/libc.so.6(+0x7f3e4)[0x7f4d50cbc3e4]
Jan 22 13:22:58 l-test njt.fms[5839]: /lib64/libc.so.6(+0x814db)[0x7f4d50cbe4db]
Jan 22 13:22:58 l-test njt.fms[5839]: /lib64/libfontconfig.so.1(FcFontSetDestroy+0x42)[0x7f4a70a0d682]
Jan 22 13:22:58 l-test njt.fms[5839]: /lib64/libgdiplus.so.0(+0x1448e)[0x7f4a7d00e48e]
Jan 22 13:22:58 l-test njt.fms[5839]: /lib64/libgdiplus.so.0(GdipGetFontCollectionFamilyCount+0x36)[0x7f4a7d00eb56]
Jan 22 13:22:58 l-test njt.fms[5839]: [0x7f4cdc6e0f09]
Jan 22 13:22:58 l-test njt.fms[5839]: ======= Memory map: ========
Jan 22 13:22:58 l-test njt.fms[5839]: 00400000-00411000 r-xp 00000000 fd:01 1314605                            /usr/share/dotnet/dotnet
Jan 22 13:22:58 l-test njt.fms[5839]: 00610000-00611000 r--p 00010000 fd:01 1314605                            /usr/share/dotnet/dotnet
Jan 22 13:22:58 l-test njt.fms[5839]: 00611000-00612000 rw-p 00011000 fd:01 1314605                            /usr/share/dotnet/dotnet
Jan 22 13:22:58 l-test njt.fms[5839]: 010ef000-03022000 rw-p 00000000 00:00 0                                  [heap]
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a68df6000-7f4a68df7000 ---p 00000000 00:00 0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a68df7000-7f4a695f7000 rw-p 00000000 00:00 0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a695f7000-7f4a695f8000 ---p 00000000 00:00 0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a695f8000-7f4a69df8000 rw-p 00000000 00:00 0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a69df8000-7f4a69df9000 ---p 00000000 00:00 0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a69df9000-7f4a6a5f9000 rw-p 00000000 00:00 0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a6a5f9000-7f4a6a609000 r-xp 00000000 fd:01 672887                     /usr/lib64/libGLX.so.0.0.0
Jan 22 13:22:58 l-test njt.fms[5839]: 7f4a6a609000-7f4a6a809000 ---p 00010000 fd:01 672887                     /usr/lib64/libGLX.so.0.0.0
Jan 22 13:22:58 l-test systemd[1]: njt.fms.service: main process exited, code=killed, status=6/ABRT
Jan 22 13:22:58 l-test systemd[1]: Unit njt.fms.service entered failed state.
Jan 22 13:22:58 l-test systemd[1]: njt.fms.service failed.

是libgdiplus出問題無疑了,但問題在於這個錯誤無法重現,程序跑一兩天才會出現,我們的程序間接使用了“GdipGetFontCollectionFamilyCount”函數,參數並無不妥,要解決就比較麻煩了。只能尋找變通方案,難不成要切回SixLabors.ImageSharp.Drawing?——還真是,我找到了微軟官方的一段說明:

地址:https://docs.microsoft.com/en-us/dotnet/api/system.drawing?view=dotnet-plat-ext-5.0

它竟然不建議我們在ASP.NET Core中使用System.Drawing,而是另外推薦了ImageSharp,之前的努力都白費了,究其原因就是操作系統圖形接口上的鴻溝,System.Drawing是一套針對GDI+的接口,GDI即Windows原生的圖形接口,GDI+是對GDI的增強,比如能在底層使用DirectDraw來加速圖形繪制,支持漸變色渲染和一些動畫效果等,這套接口是針對Windows的,要在別的系統中實現這么一套接口有些難,底層實現有太多不一樣,甚至在沒有圖形界面的Windows(Windows Server Core了解一下)中估計都成問題,所以官方也不保證System.Drawing一定好用,但由於GDI+的使用慣性很大,也不能完全把它舍棄,再說在一般的Windows環境下,開發個桌面程序啥的它是一點問題都沒有的。

我最后還是不得不把相關代碼切回SixLabors.ImageSharp.Drawing,中間又改了不少東西,不算太難,但也有些工作量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM