日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET 6 攻略大全(二)

發布時間:2023/12/4 asp.net 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET 6 攻略大全(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方藍字

關注我們

(本文閱讀時間:15分鐘)

接上篇內容,本篇文章將介紹:Arm64、容器、支持 OpenTelemetry 指標、Windows Forms 的相關攻略。?

Arm64

這些天來,對于筆記本電腦、云硬件和其他設備來說,Arm64 令人興奮不已。我們對 .NET 團隊感到同樣興奮,并正在盡最大努力跟上這一行業趨勢。我們直接與 Arm Holdings、Apple 和 Microsoft 的工程師合作,以確保我們的實施是正確和優化的,并且我們的計劃保持一致。這些密切的合作伙伴關系對我們幫助很大。

  • 特別感謝 Apple 在 M1 芯片發布之前向我們的團隊發送了一蒲式耳 Arm64 開發套件供我們使用,并提供了重要的技術支持。

  • 特別感謝 Arm Holdings,他們的工程師對我們的 Arm64 更改進行了代碼審查,并進行了性能改進。

在此之前,我們通過 .NET Core 3.0 和 Arm32 添加了對 Arm64 的初始支持。該團隊在最近的幾個版本中都對 Arm64 進行了重大投資,并且在可預見的未來這將繼續下去。在 .NET 6 中,我們主要關注在 macOS 和 Windows Arm64 操作系統上支持新的 Apple Silicon 芯片和x64 仿真場景。

您可以在 macOS 11+ 和 Windows 11+ Arm64 操作系統上安裝 Arm64 和 x64 版本的 .NET。我們必須做出多種設計選擇和產品更改以確保其奏效。

我們的策略是“親原生架構”。我們建議您始終使用與原生架構相匹配的 SDK,即 macOS 和 Windows Arm64 上的 Arm64 SDK。SDK 是大量的軟件。在 Arm64 芯片上本地運行的性能將比仿真高得多。我們更新了 CLI 以簡化操作。我們永遠不會專注于優化模擬 x64。

默認情況下,如果您dotnet run是帶有 Arm64 SDK 的 .NET 6 應用程序,它將作為 Arm64 運行。您可以使用參數輕松切換到以 x64 運行,例如-adotnet run -a x64. 相同的論點適用于其他 CLI 動詞。有關更多信息,請參閱適用于 macOS 和 Windows Arm64 的 .NET 6 RC2 更新。

我想確保涵蓋其中的一個微妙之處。當您使用-a x64時,SDK 仍以 Arm64 方式原生運行。.NET SDK 體系結構中存在進程邊界的固定點。在大多數情況下,一個進程必須全是 Arm64 或全是 x64。我正在簡化一點,但 .NET CLI 會等待 SDK 架構中的最后一個進程創建,然后將其作為您請求的芯片架構(如 x64)啟動。這就是您的代碼運行的過程。這樣,作為開發人員,您可以獲得 Arm64 的好處,但您的代碼可以在它需要的過程中運行。這僅在您需要將某些代碼作為 x64 運行時才相關。如果你不這樣做,那么你可以一直以 Arm64 的方式運行所有東西,這很棒。

Arm64 支持

對于 macOS 和 Windows Arm64,以下是您需要了解的要點:

  • 支持并推薦 .NET 6 Arm64 和 x64 SDK。

  • 支持所有支持的 Arm64 和 x64 運行時。

  • .NET Core 3.1 和 .NET 5 SDK 可以工作,但提供的功能較少,并且在某些情況下不受完全支持。

  • dotnet test 尚未與 x64 仿真一起正常工作。我們正在努力。dotnet test 將作為 6.0.200 版本的一部分進行改進,并且可能更早。

有關更多完整信息,請參閱.NET 對 macOS 和 Windows Arm64的支持。

此討論中缺少 Linux。它不像 macOS 和 Windows 那樣支持 x64 仿真。因此,這些新的 CLI 特性和支持方法并不直接適用于 Linux,Linux 也不需要它們。

視窗 Arm64

我們有一個簡單的工具來演示.NET 運行的環境。

C:Usersrich>dotnet tool install -g dotnet-runtimeinfo You can invoke the tool using the following command: dotnet-runtimeinfo Tool 'dotnet-runtimeinfo' (version '1.0.5') was successfully installed.C:Usersrich>dotnet runtimeinfo4242 ,d ,d42 42 42,adPPYb,42 ,adPPYba, MM42MMM 8b,dPPYba, ,adPPYba, MM42MMM a8" `Y42 a8" "8a 42 42P' `"8a a8P_____42 42 8b 42 8b d8 42 42 42 8PP""""""" 42 "8a, ,d42 "8a, ,a8" 42, 42 42 "8b, ,aa 42,`"8bbdP"Y8 `"YbbdP"' "Y428 42 42 `"Ybbd8"' "Y428

**.NET information

Version: 6.0.0

FrameworkDescription: .NET 6.0.0-rtm.21522.10

Libraries version: 6.0.0-rtm.21522.10

Libraries hash: 4822e3c3aa77eb82b2fb33c9321f923cf11ddde6

**Environment information

ProcessorCount: 8

OSArchitecture: Arm64

OSDescription: Microsoft Windows 10.0.22494

OSVersion: Microsoft Windows NT 10.0.22494.0

如您所見,該工具在 Windows Arm64 上本機運行。我將向您展示 ASP.NET Core 的樣子。

macOS Arm64

您可以看到在 macOS Arm64 上的體驗是相似的,并且還展示了架構目標。

rich@MacBook-Air?app?%?dotnet?--version 6.0.100 rich@MacBook-Air?app?%?dotnet?--info?|?grep?RIDRID:?????????osx-arm64 rich@MacBook-Air?app?%?cat?Program.cs? using?System.Runtime.InteropServices; using?static?System.Console; WriteLine($"Hello,?{RuntimeInformation.OSArchitecture}?from?{RuntimeInformation.FrameworkDescription}!"); rich@MacBook-Air?app?%?dotnet?run Hello,?Arm64?from?.NET?6.0.0-rtm.21522.10! rich@MacBook-Air?app?%?dotnet?run?-a?x64 Hello,?X64?from?.NET?6.0.0-rtm.21522.10! rich@MacBook-Air app %

這張圖片展示了 Arm64 執行是 Arm64 SDK 的默認設置,以及使用-a參數在目標 Arm64 和 x64 之間切換是多么容易。完全相同的體驗適用于 Windows Arm64。

此圖像演示了相同的內容,但使用的是 ASP.NET Core。我正在使用與您在上圖中看到的相同的 .NET 6 Arm64 SDK。

Arm64 上的 Docker

Docker 支持在本機架構和仿真中運行的容器,本機架構是默認的。這看起來很明顯,但當大多數 Docker Hub 目錄都是面向 x64 時,這可能會讓人感到困惑。您可以使用--platform linux/amd64來請求 x64 圖像。

我們僅支持在 Arm64 操作系統上運行 Linux Arm64 .NET 容器映像。這是因為我們從不支持在QEMU中運行 .NET ,這是 Docker 用于架構模擬的。看來這可能是由于 QEMU 的限制。

???????????????????????????????????????

此圖像演示了我們維護的控制臺示例:mcr.microsoft.com/dotnet/samples. 這是一個有趣的示例,因為它包含一些基本邏輯,用于打印您可以使用的 CPU 和內存限制信息。我展示的圖像設置了 CPU 和內存限制。

自己試試吧:docker run --rm mcr.microsoft.com/dotnet/samples

Arm64?性能

Apple Silicon 和 x64 仿真支持項目非常重要,但是,我們也普遍提高了 Arm64 性能。

此圖像演示了將堆棧幀的內容清零的改進,這是一種常見的操作。綠線是新行為,而橙色線是另一個(不太有益的)實驗,兩者都相對于基線有所改善,由藍線表示。對于此測試,越低越好。

容器

.NET 6 更適合容器,主要基于本文中討論的所有改進,適用于 Arm64 和 x64。我們還進行了有助于各種場景的關鍵更改。使用 .NET 6 驗證容器改進演示了其中一些改進正在一起測試。

Windows 容器改進和新環境變量也包含在 11 月 9 日(明天)發布的11 月 .NET Framework 4.8 容器更新中。

發布說明可在我們的 docker 存儲庫中找到:

  • .NET 6 容器發行說明

  • .NET Framework 4.8 2021 年 11 月容器發行說明

Windows 容器

.NET 6 增加了對 Windows 進程隔離容器的支持。如果您在 Azure Kubernetes 服務 (AKS) 中使用 Windows 容器,那么您依賴于進程隔離的容器。進程隔離容器可以被認為與 Linux 容器非常相似。Linux 容器使用cgroups,Windows 進程隔離容器使用Job Objects。Windows 還提供 Hyper-V 容器,通過更強大的虛擬化提供更大的隔離。Hyper-V 容器的 .NET 6 沒有任何變化。

此更改的主要價值是現在 Environment.ProcessorCount 將使用 Windows 進程隔離容器報告正確的值。如果在 64 核機器上創建 2 核容器,Environment.ProcessorCount 將返回2. 在以前的版本中,此屬性將報告機器上的處理器總數,與 Docker CLI、Kubernetes 或其他容器編排器/運行時指定的限制無關。此值被 .NET 的各個部分用于擴展目的,包括 .NET 垃圾收集器(盡管它依賴于相關的較低級別的 API)。社區庫也依賴此 API 進行擴展。

我們最近在 AKS 上使用大量 pod 在生產中的 Windows 容器上與客戶驗證了這一新功能。他們能夠以 50% 的內存(與他們的典型配置相比)成功運行,這是以前導致異常的OutOfMemoryException水平StackOverflowException。他們沒有花時間找到最低內存配置,但我們猜測它明顯低于他們典型內存配置的 50%。由于這一變化,他們將轉向更便宜的 Azure 配置,從而節省資金。只需升級即可,這是一個不錯的、輕松的勝利。

優化縮放

我們從用戶那里聽說,某些應用程序在 Environment.ProcessorCount 報告正確的值時無法實現最佳擴展。如果這聽起來與您剛剛閱讀的有關 Windows 容器的內容相反,那么它有點像。.NET 6 現在提供 DOTNET_PROCESSOR_COUNT 環境變量來手動控制 Environment.ProcessorCount 的值。在典型的用例中,應用程序可能在 64 核機器上配置為 4 核,并且在 8 或 16 核方面擴展得最好。此環境變量可用于啟用該縮放。

這個模型可能看起來很奇怪,其中Environment.ProcessorCount和--cpus(通過 Docker CLI)值可能不同。默認情況下,容器運行時面向核心等價物,而不是實際核心。這意味著,當你說你想要 4 個核心時,你得到的 CPU 時間與 4 個核心相當,但你的應用程序可能(理論上)在更多的核心上運行,甚至在短時間內在 64 核機器上運行所有 64 個核心。這可能使您的應用程序能夠在超過 4 個線程上更好地擴展(繼續示例),并且分配更多可能是有益的。這假定線程分配基于Environment.ProcessorCount 的值。如果您選擇設置更高的值,您的應用程序可能會使用更多內存。對于某些工作負載,這是一個簡單的權衡。至少,這是一個您可以測試的新選項。

Linux 和 Windows 容器均支持此新功能。

Docker 還提供了一個 CPU 組功能,您的應用程序可以關聯到特定的內核。在這種情況下不建議使用此功能,因為應用程序可以訪問的內核數量是具體定義的。我們還看到了將它與 Hyper-V 容器一起使用時的一些問題,并且它并不是真正適用于那種隔離模式。

Debian 11“bullseye”

我們密切關注 Linux 發行版的生命周期和發布計劃,并嘗試代表您做出最佳選擇。Debian 是我們用于默認 Linux 映像的 Linux 發行版。如果您6.0從我們的一個容器存儲庫中提取標簽,您將提取一個 Debian 映像(假設您使用的是 Linux 容器)。對于每個新的 .NET 版本,我們都會考慮是否應該采用新的 Debian 版本。

作為一項政策,我們不會為了方便標簽而更改 Debian 版本,例如6.0, mid-release。如果我們這樣做了,某些應用程序肯定會崩潰。這意味著,在發布開始時選擇 Debian 版本非常重要。此外,這些圖像得到了很多使用,主要是因為它們是“好標簽”的引用。

Debian 和 .NET 版本自然不會一起計劃。當我們開始 .NET 6 時,我們看到 Debian “bullseye” 可能會在 2021 年發布。我們決定從發布開始就押注于 Bullseye。我們開始使用.NET 6 Preview 1發布基于靶心的容器映像,并決定不再回頭。賭注是 .NET 6 版本會輸掉與靶心版本的競爭。到 8 月 8 日,我們仍然不知道 Bullseye 什么時候發貨,距離我們自己的版本發布還有三個月,即 11 月 8 日。我們不想在預覽版 Linux 上發布生產 .NET 6,但我們堅持我們會輸掉這場競賽的計劃很晚。

當 Debian 11 “bullseye”于 8 月 14 日發布時,我們感到非常驚喜。我們輸掉了比賽,但贏得了賭注。這意味著默認情況下,.NET 6 用戶從第一天開始就可以獲得最佳和最新的 Debian。我們相信 Debian 11 和 .NET 6 將是許多用戶的絕佳組合。抱歉,克星,我們中了靶心。

較新的發行版在其軟件包提要中包含各種軟件包的較新主要版本,并且通常可以更快地獲得CVE 修復。這是對較新內核的補充。新發行版可以更好地為用戶服務。

再往前看,我們很快就會開始計劃對Ubuntu 22.04的支持。Ubuntu是另一個 Debian 系列發行版,深受 .NET 開發人員的歡迎。我們希望為新的 Ubuntu LTS 版本提供當日支持。

向 Tianon Gravi 致敬,感謝他們為社區維護 Debian 映像并在我們有問題時幫助我們。

Dotnet Monitor

dotnet monitor 是容器的重要診斷工具。它作為 sidecar 容器鏡像已經有一段時間了,但處于不受支持的“實驗”狀態。作為 .NET 6 的一部分,我們正在發布一個基于 .NET 6 的 dotnet monitor映像,該映像在生產中得到完全支持。

dotnet monitor 已被 Azure App Service 用作其 ASP.NET Core Linux 診斷體驗的實現細節。這是預期的場景之一,建立在 dotnet monitor 之上,以提供更高級別和更高價值的體驗。

您現在可以拉取新圖像:

docker pull mcr.microsoft.com/dotnet/monitor:6.0

dotnet monitor 使從 .NET 進程訪問診斷信息(日志、跟蹤、進程轉儲)變得更加容易。在臺式機上訪問所需的所有診斷信息很容易,但是,這些熟悉的技術在使用容器的生產環境中可能不起作用。dotnet monitor 提供了一種統一的方式來收集這些診斷工件,無 論是在您的桌面計算機上還是在 Kubernetes 集群中運行。收集這些診斷工件有兩種不同的機制:

  • 用于臨時收集工件的 HTTP API 。當您已經知道您的應用程序遇到問題并且您有興趣收集更多信息時,您可以調用這些 API 端點。

  • 基于規則的配置觸發器,用于始終在線收集工件。您可以配置規則以在滿足所需條件時收集診斷數據,例如,當您持續高 CPU 時收集進程轉儲。

dotnet monitor 為 .NET 應用程序提供了一個通用的診斷 API,可以使用任何工具在任何地方工作。“通用 API”不是 .NET API,而是您可以調用和查詢的 Web API。dotnet monitor 包括一個 ASP.NET Web 服務器,它直接與 .NET 運行時中的診斷服務器交互并公開來自診斷服務器的數據。的設計 dotnet monitor 可實現生產中的高性能監控和安全使用,以控制對特權信息的訪問。dotnet monitor 通過非 Internet 可尋址的 unix domain socket 與運行時交互——跨越容器邊界。該模型通信模型非常適合此用例。

結構化 JSON 日志

JSON 格式化程序現在是 aspnet.NET 6 容器映像中的默認控制臺記錄器。.NET 5 中的默認設置為簡單的控制臺格式化程序。進行此更改是為了使默認配置與依賴機器可讀格式(如 JSON)的自動化工具一起使用。

圖像的輸出現在如下所示 aspnet:

$ docker run --rm -it -p 8000:80 mcr.microsoft.com/dotnet/samples:aspnetapp {"EventId":60,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Storing keys in a directory u0027/root/.aspnet/DataProtection-Keysu0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","State":{"Message":"Storing keys in a directory u0027/root/.aspnet/DataProtection-Keysu0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","path":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"Storing keys in a directory u0027{path}u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."}} {"EventId":35,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"No XML encryptor configured. Key {86cafacf-ab57-434a-b09c-66a929ae4fd7} may be persisted to storage in unencrypted form.","State":{"Message":"No XML encryptor configured. Key {86cafacf-ab57-434a-b09c-66a929ae4fd7} may be persisted to storage in unencrypted form.","KeyId":"86cafacf-ab57-434a-b09c-66a929ae4fd7","{OriginalFormat}":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."}} {"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://[::]:80","State":{"Message":"Now listening on: http://[::]:80","address":"http://[::]:80","{OriginalFormat}":"Now listening on: {address}"}} {"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrlu002BC to shut down.","State":{"Message":"Application started. Press Ctrlu002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrlu002BC to shut down."}} {"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Production","State":{"Message":"Hosting environment: Production","envName":"Production","{OriginalFormat}":"Hosting environment: {envName}"}} {"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content?root?path:?/app","State":{"Message":"Content?root?path:?/app","contentRoot":"/app","{OriginalFormat}":"Content?root?path:?{contentRoot}"}}

Logging__Console__FormatterName 可以通過設置或取消設置環境變量或通過代碼更改來更改記錄器格式類型(有關更多詳細信息,請參閱控制臺日志格式)。

更改后,您將看到如下輸出(就像 .NET 5 一樣):

$ docker run --rm -it -p 8000:80 -e Logging__Console__FormatterName="" mcr.microsoft.com/dotnet/samples:aspnetapp warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]No XML encryptor configured. Key {8d4ddd1d-ccfc-4898-9fe1-3e7403bf23a0} may be persisted to storage in unencrypted form. info: Microsoft.Hosting.Lifetime[14]Now listening on: http://[::]:80 info: Microsoft.Hosting.Lifetime[0]Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0]Hosting environment: Production info: Microsoft.Hosting.Lifetime[0]Content?root?path:?/app

注意:此更改不會影響開發人員計算機上的 .NET SDK,例如 dotnet run. 此更改特定于 aspnet 容器映像。

支持 OpenTelemetry 指標

作為我們關注可觀察性的一部分,我們一直在為最后幾個 .NET 版本添加對 OpenTelemetry 的支持。在 .NET 6 中,我們添加了對 OpenTelemetry Metrics API的支持。通過添加對 OpenTelemetry 的支持,您的應用程序可以與其他 OpenTelemetry 系統無縫互操作。

System.Diagnostics.Metrics 是 OpenTelemetry Metrics API 規范的 .NET 實現。Metrics API 是專門為處理原始測量而設計的,目的是高效、同時地生成這些測量的連續摘要。

API 包括 Meter 可用于創建儀器對象的類。API 公開了四個工具類:Counter、Histogram、ObservableCounter 和 ObservableGauge 以支持不同的度量方案。此外,API 公開 MeterListener 該類以允許收聽儀器記錄的測量值,以用于聚合和分組目的。

OpenTelemetry .NET 實現將被擴展以使用這些新的 API,這些 API 添加了對 Metrics 可觀察性場景的支持。

▌圖書館測量記錄示例

Meter meter = new Meter("io.opentelemetry.contrib.mongodb", "v1.0");Counter<int> counter = meter.CreateCounter<int>("Requests");counter.Add(1);counter.Add(1,?KeyValuePair.Create<string,?object>("request",?"read"));

▌聽力示例

MeterListener listener = new MeterListener();listener.InstrumentPublished = (instrument, meterListener) =>{if (instrument.Name == "Requests" && instrument.Meter.Name == "io.opentelemetry.contrib.mongodb"){meterListener.EnableMeasurementEvents(instrument, null);}};listener.SetMeasurementEventCallback<int>((instrument, measurement, tags, state) =>{Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");});listener.Start();

Windows Forms

我們繼續在 Windows 窗體中進行重要改進。.NET 6 包括更好的控件可訪問性、設置應用程序范圍的默認字體、模板更新等的能力。

▌可訪問性改進

在此版本中,我們添加了用于CheckedListBox、LinkLabel、Panel、ScrollBar和TabControlTrackBar的UIA 提供程序,它們使講述人等工具和測試自動化能夠與應用程序的元素進行交互。

▌默認字體

您現在可以使用.Application.SetDefaultFont

void Application.SetDefaultFont(Font font)

▌最小的應用程序

以下是帶有 .NET 6 的最小 Windows 窗體應用程序:

class Program {[STAThread]static void Main(){ApplicationConfiguration.Initialize();Application.Run(new Form1());} }

作為 .NET 6 版本的一部分,我們一直在更新大多數模板,使其更加現代和簡約,包括 Windows 窗體。我們決定讓 Windows 窗體模板更傳統一些,部分原因是需要將[STAThread]屬性應用于應用程序入口點。然而,還有更多的戲劇而不是立即出現在眼前。

ApplicationConfiguration.Initialize()是一個源生成 API,它在后臺發出以下調用:

Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.SetDefaultFont(new Font(...)); Application.SetHighDpiMode(HighDpiMode.SystemAware);

這些調用的參數可通過 csproj 或 props 文件中的 MSBuild 屬性進行配置。

Visual Studio 2022 中的 Windows 窗體設計器也知道這些屬性(目前它只讀取默認字體),并且可以向您顯示您的應用程序,就像它在運行時一樣:

▌模板更新

C# 的 Windows 窗體模板已更新,以支持新的應用程序引導、global using 指令、文件范圍的命名空間和可為空的引用類型。

▌更多運行時 designers

現在您可以構建通用設計器(例如,報表設計器),因為 .NET 6 具有設計器和與設計器相關的基礎架構所缺少的所有部分。有關詳細信息,請參閱此博客文章。

  • 博客文章

    https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0-preview-5/#more-runtime-designers

未完待續

更多內容請繼續關注明日(周日)文章

?了解更多.NET 6?

總結

以上是生活随笔為你收集整理的.NET 6 攻略大全(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。