RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1295270
Accepted
John
John
Asked:2022-06-15 04:52:59 +0000 UTC2022-06-15 04:52:59 +0000 UTC 2022-06-15 04:52:59 +0000 UTC

为什么我们需要后端的同步上下文?

  • 772

据我了解,同步上下文的使用是可以让你在UI线程上继续(否则我们将无法更新UI,如果我们尝试,就会出现异常)。

1.正确理解?

我尝试在 .NET Core 2.2 控制台应用程序中执行该示例。使用长时间运行的异步操作创建了一个等待,与等待之前相同的上下文将用于继续。鉴于我知道的上下文存在的原因,我假设线程应该与等待之前相同。但是控制台的输出继续显示,而不是等待之前的线程 ID。

据我了解,由于(.NET Core 控制台)在执行时根本没有同步上下文。确实,那里没有UI,它有什么用。我想它只会像我想的那样在 UWP 和 WPF 等 UI 项目上工作。

但在这里:

我听说在 .NET Core 中不需要应用 ConfigureAwait(false)。是这样吗?

有信息表明 .NET Framework 在非 UI 项目中具有自己的上下文 + 可以在核心项目中创建自定义同步上下文。

2. 为什么在 UI 项目之外创建/使用上下文会有用?

3、为什么.NET Framework默认有同步上下文?

  1. 我不确定我是否正确理解支持在 .NET Core 后端使用 ConfigureAwait(false) 的论点。我是否正确理解它只有在以下情况下才有意义:(1)我选择了我在背面使用的逻辑的一部分,在一个库中并在 UI 项目中重用它。(2)我害怕第三 -可以带来自己的上下文并以某种方式种植主要项目的派对库。虽然为什么后面需要这样的库也是一个问题。 ?
c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Pavel Mayorov
    2022-06-18T16:28:34Z2022-06-18T16:28:34Z

    旧的 ASP.NET 有许多全局可用的对象,主要的一个是HttpContext.Current. 顺便说一句,ASP.NET Core 有一个用于相同目的的接口IHttpContextAccessor,但它没有被广泛使用:现在很可能编写一个复杂的 Web 应用程序甚至一次都不使用这个接口——而以前它HttpContext.Current总是直接使用或间接执行任何请求时。

    最初HttpContext.Current只是一个 ThreadStatic 字段,但是在 ASP.NET 中加入异步后,结果发现 ThreadStatic 字段的值在执行异步操作后“丢失”了。但是如果它IHttpContextAccessor使用一种机制来解决这个问题AsyncLocal,那么 ASP.NET 的创建者就无法做到这一点,因为 ASP.NET 比这种机制更古老。这就是他们提出使用同步上下文的想法的地方。

    实际上,SynchronizationContextASP.NET 中的主要使用点是HttpContext.Current异步操作完成后的恢复。

    同时,同步上下文执行以下任务:

    1. 延续的序列化 - 所有异步延续都被排队以避免在访问共享对象时可能出现的竞争 - 在新的 ASP.NET Core 中,此任务被分配给程序员,部分分配给 await 运算符;

    2. 考虑异步操作以了解请求处理何时结束 - 在新的 ASP.NET Core 中,使用任务(Task 和 ValueTask)代替。

    PS 同步上下文实现链接 - https://referencesource.microsoft.com/#system.web/AspNetSynchronizationContext.cs

    • 14
  2. Mark Shevchenko
    2022-06-18T22:54:25Z2022-06-18T22:54:25Z

    同步上下文是一种允许您解决两个相似任务的机制。它允许异步代码在进行异步调用的同一线程上执行,或者如果继续在不同线程上启动,它允许恢复线程绑定的静态值。

    第一个案例是关于 UI 的,第二个案例是关于后端的。理论上,您可以创建自己的同步上下文并实现自己的逻辑,但我还没有听说过这种实际的实现。

    为什么在 UI 中使用同步上下文?Windows 窗口子系统是在单处理器系统时代设计的,并且在单线程环境中运行良好。它也适用于多线程,但有很大的局限性。您可以SendMessage从不同的线程调用该函数,但它是同步工作的。如果SendMessage当时从另一个线程执行,您的线程将等待。

    异步任务旨在提高 CPU 利用率,但这仅在它们完成得非常快时才会发生。等待SendMessage可能很长,因此 Windows 的创建者只是决定只有来自 UI 线程的任务才能调用它。程序中只有一个UI线程,所以所有这样的调用都是顺序执行的,互不干扰。

    SendMessage用于更改和获取Windows中所有控件的所有属性的值。这就是上帝的功能。

    如果我们想改变一些东西,比如标签的文本或输入字段的颜色,我们必须在主线程上做,而 UI 应用程序同步上下文可以帮助我们做到这一点。

    为什么要在后端使用同步上下文?相邻的答案已经涵盖了这个话题,但我会以我自己的方式回答,据我所知。

    从历史上看,ASP.NET 应用程序只是多线程的。对于每个 Web 请求,服务器都会创建一个线程。来自不同用户的线程不会相互混合,因此可以方便地将请求中的重要数据存储在静态线程变量中。

    .NET 中有一个平台支持的概念,并不是每个人都记得,因为无处不在的 DI 正在消亡。

    请求中的重要数据是什么?首先,这是代表其提出请求的用户;第二,用户的文化。

    如果您需要应用程序安全性,您可以实现身份验证:Basic、Digest、Windows Integrated 或 Bearer。有关当前用户的信息出现在标题中Authorization。ASP.NET 检索此信息并将其存储在HttpContext.User.

    多亏了这一点,授权代码变得更简单,您可以显示用户名或制作个人资料页面。

    用户的文化是从标题中检索的Accepted-Languages。如果它出现在那里ru-RU,则该网站了解有必要以俄语提供信息。

    整个设计在多线程环境中运行良好,但在异步环境中停止运行。您的代码的延续可能会在不同的线程上执行。

    这意味着在await你突然改变用户和他的语言之后。

    为了避免这种情况,ASP.NET 的创建者为 web 实现了一个同步上下文,该上下文在HttpContext.Current.

    然而,这个在每次异步调用上都执行的过程非常耗时。大部分代码不使用文化或当前用户,因此可以在任何空闲线程上运行而无需任何前奏。我们记得,为此我们需要调用ConfigureAwait(false).

    只有普通程序员才不会打扰这个调用,所以无论如何同步上下文总是在使用中。

    我认为这就是 .NET Core 完全放弃同步上下文的原因。ConfigureAwait(false)对网络没有意义。

    该实例HttpContext可作为控制器的属性使用,因此您无需调用HttpContext.Current.

    • 8

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5