跳至页脚内容
.NET 帮助

Polly 重试(开发人员如何使用)

优雅地处理瞬时故障、超时和异常对于构建稳健和弹性应用程序至关重要。 Polly 是一个流行的 .NET 库,提供弹性和瞬时故障处理能力。 在其众多功能中,“重试”是使用最广泛的策略之一。

在本文中,我们将深入探讨Polly 在C# 中的重试策略,探索其用法、配置选项并提供实用的代码示例。 此外,我们将使用 IronPDF 库进行 PDF 生成与 Polly 重试策略结合以生成表单请求结果的PDF。

什么是 Polly 重试?

Polly 重试是一种由 Polly 库提供的策略,允许开发人员自动重试可能由于错误或瞬时故障而失败的操作。 瞬时故障是网络故障、服务不可用或其他瞬时问题引起的临时错误。

通过 Polly 的重试策略,可以定义重试操作的规则,包括最大重试次数、多个重试之间的延迟以及重试失败请求的条件。这有助于构建能够从临时故障中恢复而不崩溃或对最终用户造成干扰的弹性应用程序。

开始使用 Polly 重试

在深入代码示例之前,让我们建立基本的理解如何在 C# 项目中安装和配置 Polly。

安装 Polly

您可以通过以下命令在 NuGet 程序包管理器控制台中安装 Polly:

Install-Package Polly

或通过 .NET CLI:

dotnet add package Polly

添加 Polly 使用语句

在您的 C# 文件中,包含 Polly 命名空间:

using Polly;
using Polly;
Imports Polly
$vbLabelText   $csharpLabel

基本重试策略示例

让我们从一个简单的示例开始,我们重试一个模拟从远程服务获取数据的操作。我们将设置一个最大重试 3 次和每次重试之间固定 2 秒超时时间延迟的重试策略。

using System;
using System.Net.Http;
using Polly;

namespace PollyRetryExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // Define a retry policy that handles HttpRequestException with a maximum of 3 retries
            var retryPolicy = Policy
                .Handle<HttpRequestException>() // Specify the exception type to handle
                .WaitAndRetry(
                    3, // Max retry attempts
                    retryAttempt => TimeSpan.FromSeconds(2), // Fixed retry delay
                    (exception, timeSpan, retryCount, context) =>
                    {
                        Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message);
                    });

            try
            {
                // Execute the action within the context of the retry policy
                retryPolicy.Execute(() =>
                {
                    FetchDataFromRemoteService();
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed after 3 retries: {0}", ex.Message);
            }
        }

        // Simulate fetching data that throws HttpRequestException
        public static void FetchDataFromRemoteService()
        {
            throw new HttpRequestException("Failed to fetch data from remote service");
        }
    }
}
using System;
using System.Net.Http;
using Polly;

namespace PollyRetryExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // Define a retry policy that handles HttpRequestException with a maximum of 3 retries
            var retryPolicy = Policy
                .Handle<HttpRequestException>() // Specify the exception type to handle
                .WaitAndRetry(
                    3, // Max retry attempts
                    retryAttempt => TimeSpan.FromSeconds(2), // Fixed retry delay
                    (exception, timeSpan, retryCount, context) =>
                    {
                        Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message);
                    });

            try
            {
                // Execute the action within the context of the retry policy
                retryPolicy.Execute(() =>
                {
                    FetchDataFromRemoteService();
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed after 3 retries: {0}", ex.Message);
            }
        }

        // Simulate fetching data that throws HttpRequestException
        public static void FetchDataFromRemoteService()
        {
            throw new HttpRequestException("Failed to fetch data from remote service");
        }
    }
}
Imports System
Imports System.Net.Http
Imports Polly

Namespace PollyRetryExample
	Public Class Program
		Public Shared Sub Main(ByVal args() As String)
			' Define a retry policy that handles HttpRequestException with a maximum of 3 retries
			Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(3, Function(retryAttempt) TimeSpan.FromSeconds(2), Sub(exception, timeSpan, retryCount, context)
				Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message)
			End Sub)

			Try
				' Execute the action within the context of the retry policy
				retryPolicy.Execute(Sub()
					FetchDataFromRemoteService()
				End Sub)
			Catch ex As Exception
				Console.WriteLine("Failed after 3 retries: {0}", ex.Message)
			End Try
		End Sub

		' Simulate fetching data that throws HttpRequestException
		Public Shared Sub FetchDataFromRemoteService()
			Throw New HttpRequestException("Failed to fetch data from remote service")
		End Sub
	End Class
End Namespace
$vbLabelText   $csharpLabel

在此示例中:

  • Handle<HttpRequestException>() 指定我们想要处理 HttpRequestException 并在发生时重试操作。
  • WaitAndRetry() 配置重试策略,重试 3 次,每次重试之间固定延迟 2 秒(指定最大持续时间)。
  • onRetry 委托在发生重试时记录一条消息。

Polly 重试(开发人员如何工作):图 1

高级重试策略配置

指数回退

指数退避是一种流行的重试策略,其中请求和重试之间的延迟指数增加。 Polly 提供了一种使用 WaitAndRetry() 实现指数退避的便捷方法。

var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(
        retryCount: 3, // Max retry attempts
        sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential delay
        onRetry: (exception, timeSpan, retryCount, context) =>
        {
            Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
        });
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(
        retryCount: 3, // Max retry attempts
        sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential delay
        onRetry: (exception, timeSpan, retryCount, context) =>
        {
            Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
        });
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(retryCount:= 3, sleepDurationProvider:= Function(attempt) TimeSpan.FromSeconds(Math.Pow(2, attempt)), onRetry:= Sub(exception, timeSpan, retryCount, context)
	Console.WriteLine($"Retry {retryCount} due to {exception.Message}")
End Sub)
$vbLabelText   $csharpLabel

Polly 重试(开发人员如何工作):图 2

与断路器重试

将重试与断路器结合使用可以通过防止服务持续失败时重复重试来进一步增强弹性。 Polly 允许您轻松结合重试和断路器策略。

// Define a circuit breaker policy
var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(
        exceptionsAllowedBeforeBreaking: 3, // Number of exceptions before breaking
        durationOfBreak: TimeSpan.FromSeconds(30), // Time circuit stays open
        onBreak: (ex, breakDelay) =>
        {
            Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.");
        },
        onReset: () =>
        {
            Console.WriteLine("Circuit reset.");
        });

// Define a retry policy
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(
        retryCount: 3, // Max retry attempts
        sleepDurationProvider: attempt => TimeSpan.FromSeconds(2), // Fixed retry delay
        onRetry: (exception, timeSpan, retryCount, context) =>
        {
            Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
        });

// Combine both policies into a single policy wrap
var policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy);
// Define a circuit breaker policy
var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(
        exceptionsAllowedBeforeBreaking: 3, // Number of exceptions before breaking
        durationOfBreak: TimeSpan.FromSeconds(30), // Time circuit stays open
        onBreak: (ex, breakDelay) =>
        {
            Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.");
        },
        onReset: () =>
        {
            Console.WriteLine("Circuit reset.");
        });

// Define a retry policy
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(
        retryCount: 3, // Max retry attempts
        sleepDurationProvider: attempt => TimeSpan.FromSeconds(2), // Fixed retry delay
        onRetry: (exception, timeSpan, retryCount, context) =>
        {
            Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
        });

// Combine both policies into a single policy wrap
var policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy);
' Define a circuit breaker policy
Dim circuitBreakerPolicy = Policy.Handle(Of HttpRequestException)().CircuitBreaker(exceptionsAllowedBeforeBreaking:= 3, durationOfBreak:= TimeSpan.FromSeconds(30), onBreak:= Sub(ex, breakDelay)
			Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.")
End Sub, onReset:= Sub()
			Console.WriteLine("Circuit reset.")
End Sub)

' Define a retry policy
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(retryCount:= 3, sleepDurationProvider:= Function(attempt) TimeSpan.FromSeconds(2), onRetry:= Sub(exception, timeSpan, retryCount, context)
	Console.WriteLine($"Retry {retryCount} due to {exception.Message}")
End Sub)

' Combine both policies into a single policy wrap
Dim policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy)
$vbLabelText   $csharpLabel

在此示例中:

  • CircuitBreaker() 定义断路器策略,该策略在 3 次异常后中断并保持开放 30 秒。
  • Policy.Wrap() 将断路器和重试策略合并为一个策略。

Polly 重试(开发人员如何工作):图 3

IronPDF简介

IronPDF C# PDF 库概述 是一个强大的 C# 库,允许开发人员在其 .NET 应用程序中创建、编辑和操作 PDF 文档。 无论您是需要创建发票、报告还是任何其他类型的 PDF 文档,IronPDF 提供了一个简化过程的直观 API。

借助 IronPDF,您可以轻松将 HTML、CSS 甚至 ASP.NET 网页转换为 PDF,使其成为众多应用程序的万能工具。 此外,它提供添加文本、图像和交互元素等高级功能,并使用加密和数字签名对 PDF 进行安全处理。

IronPDF 擅长HTML 到 PDF 转换,确保原始布局和样式的精确保留。 它非常适合从基于网页的内容(如报告、发票和文档)生成 PDF。 IronPDF 支持从 HTML 文件、URL 和原始 HTML 字符串转换为高质量 PDF 文件。

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel

与 IronPDF 结合的 Polly 重试

当使用 IronPDF 时,可能会遇到需要从外部资源获取数据或在生成 PDF 之前执行复杂操作的场景。

在这些情况下,您可能会遇到瞬时故障或临时问题,这可能导致 PDF 生成失败。 为了优雅地处理这些瞬时故障,您可以将 Polly 重试与 IronPDF 结合使用。

安装 IronPDF 和 Polly

在开始之前,确保在您的项目中安装 IronPDF NuGet 包。

Install-Package IronPdf

使用 Polly 重试与 IronPDF

让我们看看一个使用 Polly 重试来处理使用 IronPDF 生成 PDF 时瞬时故障的示例。 在以下示例中,我们将模拟从外部 API 获取数据,然后基于该数据生成 PDF。 我们将使用 Polly Retry 在发生故障时执行数据获取操作。

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

namespace IronPdfWithPollyRetry
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            // Define a retry policy with async capability
            var retryPolicy = Policy
                .Handle<HttpRequestException>() // Specify exception type to handle
                .WaitAndRetryAsync(
                    3, // Retry attempts
                    retryAttempt => TimeSpan.FromSeconds(2), // Calculated retry delay
                    (exception, timeSpan, retryCount, context) =>
                    {
                        Console.WriteLine("Retry " + retryCount + " due to " + exception.Message);
                    });

            // Execute the retry policy asynchronously
            var pdf = await retryPolicy.ExecuteAsync(async () =>
            {
                var data = await FetchDataFromExternalApiAsync(); // Fetch data from an external source
                return GeneratePdfFromData(data); // Generate PDF using fetched data
            });

            pdf.SaveAs("GeneratedDocument.pdf");
        }

        // Simulate fetching data from an external API
        static async Task<string> FetchDataFromExternalApiAsync()
        {
            await Task.Delay(100); // Simulate delay
            throw new HttpRequestException("Failed to fetch data from external API");
        }

        // Generate PDF using IronPDF based on the fetched data
        static PdfDocument GeneratePdfFromData(string data)
        {
            var htmlContent = "<html><body><h1>Data: " + data + "</h1></body></html>";
            var renderer = new ChromePdfRenderer();
            return renderer.RenderHtmlAsPdf(htmlContent);
        }
    }
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IronPdf;
using Polly;

namespace IronPdfWithPollyRetry
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            // Define a retry policy with async capability
            var retryPolicy = Policy
                .Handle<HttpRequestException>() // Specify exception type to handle
                .WaitAndRetryAsync(
                    3, // Retry attempts
                    retryAttempt => TimeSpan.FromSeconds(2), // Calculated retry delay
                    (exception, timeSpan, retryCount, context) =>
                    {
                        Console.WriteLine("Retry " + retryCount + " due to " + exception.Message);
                    });

            // Execute the retry policy asynchronously
            var pdf = await retryPolicy.ExecuteAsync(async () =>
            {
                var data = await FetchDataFromExternalApiAsync(); // Fetch data from an external source
                return GeneratePdfFromData(data); // Generate PDF using fetched data
            });

            pdf.SaveAs("GeneratedDocument.pdf");
        }

        // Simulate fetching data from an external API
        static async Task<string> FetchDataFromExternalApiAsync()
        {
            await Task.Delay(100); // Simulate delay
            throw new HttpRequestException("Failed to fetch data from external API");
        }

        // Generate PDF using IronPDF based on the fetched data
        static PdfDocument GeneratePdfFromData(string data)
        {
            var htmlContent = "<html><body><h1>Data: " + data + "</h1></body></html>";
            var renderer = new ChromePdfRenderer();
            return renderer.RenderHtmlAsPdf(htmlContent);
        }
    }
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports IronPdf
Imports Polly

Namespace IronPdfWithPollyRetry
	Public Class Program
		Public Shared Async Function Main(ByVal args() As String) As Task
			' Define a retry policy with async capability
			Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetryAsync(3, Function(retryAttempt) TimeSpan.FromSeconds(2), Sub(exception, timeSpan, retryCount, context)
				Console.WriteLine("Retry " & retryCount & " due to " & exception.Message)
			End Sub)

			' Execute the retry policy asynchronously
			Dim pdf = Await retryPolicy.ExecuteAsync(Async Function()
				Dim data = Await FetchDataFromExternalApiAsync() ' Fetch data from an external source
				Return GeneratePdfFromData(data) ' Generate PDF using fetched data
			End Function)

			pdf.SaveAs("GeneratedDocument.pdf")
		End Function

		' Simulate fetching data from an external API
		Private Shared Async Function FetchDataFromExternalApiAsync() As Task(Of String)
			Await Task.Delay(100) ' Simulate delay
			Throw New HttpRequestException("Failed to fetch data from external API")
		End Function

		' Generate PDF using IronPDF based on the fetched data
		Private Shared Function GeneratePdfFromData(ByVal data As String) As PdfDocument
			Dim htmlContent = "<html><body><h1>Data: " & data & "</h1></body></html>"
			Dim renderer = New ChromePdfRenderer()
			Return renderer.RenderHtmlAsPdf(htmlContent)
		End Function
	End Class
End Namespace
$vbLabelText   $csharpLabel

此 C# 代码演示如何使用 Polly 库为 IronPDF 生成 PDF 文档实现重试策略。 Main 方法使用 Polly 的 WaitAndRetryAsync 方法初始化了一个重试策略。

此策略指定它应该处理 HttpRequestException 并在初始尝试和重试之间最多 3 次重试,每次之间有 2 秒的延迟。 如果发生重试失败,则打印一条消息到控制台指出重试尝试次数和异常消息。

Main 方法中,重试策略逻辑使用 retryPolicy.ExecuteAsync() 异步执行。 在此执行过程中,两个异步操作被链接在一起:FetchDataFromExternalApiAsync()GeneratePdfFromData(data)

如果 FetchDataFromExternalApiAsync() 失败(因为它被故意设置为通过模拟异常失败),重试策略将捕获 HttpRequestException,记录重试尝试,并重试操作。

FetchDataFromExternalApiAsync() 方法模拟从外部 API 获取数据,带有延迟和有意抛出的 HttpRequestException,以模拟失败请求。

Polly 重试(开发人员如何工作):图 4

结论

总之,Polly 的重试策略在处理瞬时故障和确保 C# 应用程序的稳健性方面具有极大的价值。 其在配置重试尝试、延迟和条件方面的灵活性使得开发人员能够根据特定需求量身定制弹性策略。

无论是独立使用还是与库(如 IronPDF)结合使用,Polly 促进了应用程序的创建,这些应用程序可以优雅地从临时故障中恢复,提高用户体验和软件的可靠性。

通过集成 Polly 的重试功能,开发人员可以构建更具弹性的系统,这些系统可以适应和从瞬时问题中恢复,从而最终提高应用程序的整体质量和可靠性。

IronPDF 是市场上最好的 C# PDF 库,它还提供 IronPDF 试用许可,价格从 $799 美元起。

要了解使用 IronPDF 进行 HTML 到 PDF 转换,请访问以下IronPDF HTML 到 PDF 转换教程

常见问题解答

什么是 C# 中的 Polly 重试?

Polly 重试是 C# 中 Polly 库的一个功能,它允许开发人员在由于网络故障或服务不可用等临时问题导致失败时自动重试操作。这有助于通过优雅地处理瞬态故障来构建弹性应用程序。

如何使用 Polly 实现基本的重试策略?

您可以通过处理异常如 HttpRequestException 并设置其最大重试次数为三次,每次尝试之间固定延迟两秒来实现 Polly 中的基本重试策略。

Polly 中指数退避的意义是什么?

Polly 中的指数退避用于指数增加重试之间的延迟,这有助于在失败期间减少服务负载。这可以通过 Polly 的 WaitAndRetry 方法实现,该方法根据指数增长计算延迟。

如何为 C# 项目安装 Polly?

您可以使用 NuGet 包管理器控制台中的命令 Install-Package Polly 或通过 .NET CLI 使用 dotnet add package Polly 在 C# 项目中安装 Polly。

Polly 的重试策略可以与其他弹性策略结合吗?

可以,Polly 允许您通过使用 Policy.Wrap 方法将其重试策略与其他弹性策略(如断路器)结合以增强应用程序弹性并防止服务持续失败时的重复重试。

如何在C#中将HTML转换为PDF?

您可以使用 IronPDF 的方法,如 RenderHtmlAsPdf 将 HTML 字符串转换为 PDF。IronPDF 还支持将包括 CSS 在内的 HTML 文件和网页转换为 PDF 格式。

为什么 Polly 的重试策略对 C# 应用程序很重要?

Polly 的重试策略对于处理 C# 应用程序中的瞬态故障至关重要,确保稳健性,并通过允许系统从临时故障中恢复而不崩溃来改善用户体验。

如何在 PDF 生成过程中实施重试策略?

在生成 PDF 时,可以使用 Polly 实施重试策略以处理瞬态故障。通过将 Polly 的重试功能与 IronPDF 集成,可以在遇到临时网络或服务问题时多次尝试 PDF 操作。

如何安装像 IronPDF 这样的 C# PDF 库?

可以通过 NuGet 包管理器使用命令 Install-Package IronPdf 安装 IronPDF,从而允许您在 C# 应用程序中创建、编辑和操作 PDF 文档。

使用 IronPDF 进行 PDF 生成有哪些好处?

IronPDF 提供了强大的功能来在 .NET 应用程序中创建和操作 PDF 文档。它支持将 HTML、CSS 和网页转换为 PDF,添加文本和图像,并通过加密保护文档。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。