sách gpt4 ai đã đi

Cách đúng đắn để tạo ra, không phải chờ đợi và đảm bảo hoàn thành một nhiệm vụ

In lại 作者:行者123 更新时间:2023-12-05 01:04:35 36 4
mua khóa gpt4 Nike

前言:我对 C# 中任务的底层实现不太了解,只了解它们的用法。为我在下面屠宰的任何东西道歉:

对于“我怎样才能开始一项任务但不等待它?”这个问题,我找不到一个好的答案。在 C# 中。更具体地说,即使任务的上下文已完成/销毁,我如何保证任务完成?

_ = someFunctionAsync(); 对于启动和忘记任务来说是令人满意的,但是如果父级是 transient 的呢?如果任务无法在父任务之前完成怎么办?这在 Controller 方法中经常发生,以 _ = someFunctionAsync(); 方式编写的任务可能会被取消。

Mã ví dụ:

        [HttpGet]
public IActionResult Get()
{
_ = DoSomethingAsync();
return StatusCode(204);
}

为了解决这种取消,我创建了一个(相当愚蠢,imo)静态类来保留任务,以便他们有时间完成,但它不起作用,因为当父 Controller 被取消时任务被取消销毁:

    public static class IncompleteTaskManager
{
private static ConcurrentBag _incompleteTasks = new();

private static event EventHandler? _onTaskCompleted;

public static void AddTask(Task t)
{
_onTaskCompleted += (sender, task) =>
{
_incompleteTasks = new ConcurrentBag(_incompleteTasks.Where(task => task != t));
};

_incompleteTasks.Add(CreateTaskWithRemovalEvent(t));
}

private static async Task CreateTaskWithRemovalEvent(Task t)
{
await t;
_onTaskCompleted?.Invoke(null, t);
}
}

另外,这看起来很复杂,感觉像是一个简单问题的糟糕解决方案。那么,我该怎么处理呢?什么是开始一项任务,忘记它,但保证它运行完成的正确方法?

编辑 1,以防有人建议:我读过帖子建议 _ = Task.Run(async () => await someFunctionAsync()); 可能满足我的需求,但这也不是这样。虽然另一个线程运行该方法,但它的上下文也丢失了,并且该任务被取消,从而取消了子任务。

编辑 2:我意识到 Controller 示例不一定是最好的,因为我可以简单地编写不同的代码以立即响应,然后在处理 Controller 之前等待方法完成:

        [HttpGet]
public async Task Get()
{
base.Response.StatusCode = 204;
await base.Response.CompleteAsync(); //Returns 204 to caller here.
await DoSomethingAsync();
}

1 Câu trả lời

这里有很多东西要解压。我可能会错过一些细节,但让我分享一些应该奠定良好基础的东西。

从根本上说,您所问的是如何在 ASP.NET 中创建后台任务。在 .NET 4.x 中,有一个 QueueBackgroundWorkItem为此目的创建的方法:它为您的任务提供了一个新的取消 token 来使用,而不是 Controller 操作提供的取消 token ,并将您切换到您提供的操作的不同上下文。

在 asp.net 核心中,有更强大(但更复杂)的 IHostedService 实现,包括 Bối cảnhDịch vụ,但没有比 QueueBackgroundWorkItem 更简单的了。但是,the docs include an example展示了如何使用 Bối cảnhDịch vụ 来编写自己的实现。如果您使用他们的代码,您应该能够将 IBackgroundTaskQueue 注入(inject)您的 Controller 并调用 QueueBackgroundWorkItemAsync 以将后台任务排入队列。

这两种方法都需要有一些东西等待开始的任务。您永远无法真正“保证”完成任何给定任务,但它们至少可以更优雅地处理常见用例。例如,它们让您的托管环境(例如 IIS)知道某些东西仍在运行,因此它不会因为没有请求进入而自动关闭。如果托管环境被指示关闭,它可以发出信号这个事实通过取消 token ,您可以希望快速让您的任务进入安全状态以关闭而不是被随意中止。

它们还处理后台任务中未捕获异常的问题:异常被捕获并记录下来,而不是被静默吃掉或完全杀死应用程序。

这些都不能帮助您维护有关当前请求或用户等内容的上下文。这是明智的,因为重点是允许操作超出任何给定请求的范围。因此,您需要编写在这些操作中调用的任何代码,以不依赖 HttpContext/IHttpContextAccessor 或类似的任何有状态的东西。相反,在将后台任务排入队列之前从上下文中收集您需要的信息,并将该信息作为变量和参数传递给下游代码。无论如何,这通常是一种很好的做法,因为 HTTP 上下文是应该保留在 Controller 级代码中的职责,而您的大多数业务逻辑应该考虑业务级模型。通常最好尽可能避免依赖状态,以创建更可靠、可测试等的软件。

对于其他类型的应用程序,您还需要采用其他方法。通常最好对 [framework] background tasks 进行互联网搜索,其中 [framework] 是您正在使用的框架(例如 WPF)。不同的框架会有不同的限制。例如,如果您编写了一个控制台应用程序,该应用程序希望在没有命令行参数之外的任何交互的情况下运行,则从您的 Main 函数返回的 Task 可能需要等待您在其中启动的所有任务。另一方面,WPF 应用程序可能会在调用按钮单击等事件时启动多个后台任务,但有一些技巧可确保您在后台线程上执行 CPU 密集型工作,同时仅在 UI 线程上与 UI 元素交互.

关于c# - 创建、不等待和确保任务完成的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71899322/

36 4 0
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com