问题标签 [synchronizationcontext]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
6387 浏览

c# - C# async/await 代码中的“上下文”到底是什么意思?

让我们看一些简单的 C# async/await 代码,其中我在withobj之前和之后都有一个对象引用 ( )awaitConfigureAwait(false)

ConfigureAwait(false)似乎意味着 将继续编组回捕获的原始上下文- 好的,但这到底意味着什么?我已经尝试了上面的代码并且被obj 正确地引用回来(即使它在不同的线程上恢复)。

所以“上下文”似乎不是线程的工作内存(即线程本地存储)。那么“上下文”包含什么?因此,真正意味着什么

将延续编组回捕获的原始上下文

0 投票
1 回答
2481 浏览

c# - SynchronizationContext 在 Task.Run 上流动,但在 await 上不流动

在阅读了 Stephen Toub 关于 SynchronizationContext 的文章后,我对这段 .NET 4.5 代码的输出提出了一个问题:

输出是:

btnDoSomething_Click WindowsFormsSynchronizationContext

DoItAsync WindowsFormsSynchronizationContext

PerformServiceCall 1 WindowsFormsSynchronizationContext

PerformServiceCall 2 线程池任务调度器

ProcessMessage ThreadPoolTask​​Scheduler

PerformServiceCall 3 线程池任务调度器

但我希望 PerformServiceCall 1 不会出现在 WindowsFormsSynchronizationContext 上,因为文章指出“SynchronizationContext.Current 不会在等待点之间“流动”...

当使用 Task.Run 和异步 lambda 调用 PerformServiceCall 时,上下文不会被传递,如下所示:

任何人都可以澄清或指出一些关于此的文件吗?

0 投票
1 回答
159 浏览

.net - 为什么 NotifyIcon 没有设置 SynchronizationContext?

考虑这个 WinForms 程序:

NotifyIcon 是一个 WinForm 控件,并且需要一个消息循环,那么为什么声明dummycontrol(或任何 WinForms 控件)会设置一个 SynchronizationContext,而 NotifyIcon 没有呢?

0 投票
3 回答
3149 浏览

c# - 我们应该在调用异步回调的库中使用 ConfigureAwait(false) 吗?

ConfigureAwait(false)在 C# 中使用 await/async时,有很多指导方针。

似乎一般建议是ConfigureAwait(false)在库代码中使用,因为它很少依赖于同步上下文。

但是,假设我们正在编写一些非常通用的实用程序代码,它将函数作为输入。一个简单的例子可能是以下(不完整的)功能组合器,以使简单的基于任务的操作更容易:

地图:

平面图:

问题是,我们应该ConfigureAwait(false)在这种情况下使用吗?我不确定上下文捕获是如何工作的。关闭。

一方面,如果以功能方式使用组合子,则不需要同步上下文。另一方面,人们可能会滥用 API,并在提供的函数中做与上下文相关的事情。

一种选择是为每个场景(MapMapWithContextCapture或某些东西)使用单独的方法,但感觉很难看。

另一种选择可能是将选项添加到 map/flatmap from 和 into a ConfiguredTaskAwaitable<T>,但由于 awaitables 不必实现接口,这将导致大量冗余代码,在我看来更糟。

是否有一种将责任切换给调用者的好方法,这样实现的库不需要对提供的映射函数中是否需要上下文做出任何假设?

或者仅仅是一个事实,即异步方法在没有各种假设的情况下组合得不太好?

编辑

只是为了澄清一些事情:

  1. 问题确实存在。当您在实用程序函数中执行“回调”时,添加ConfigureAwait(false)将导致空同步。语境。
  2. 主要问题是我们应该如何应对这种情况。我们是否应该忽略某人可能想要使用同步的事实。上下文,或者除了添加一些重载、标志等之外,是否有一种将责任转移给调用者的好方法?

正如一些答案所提到的,可以在该方法中添加一个布尔标志,但正如我所见,这也不是很漂亮,因为它必须通过 API 一路传播(因为有更多“实用”功能,取决于上面显示的功能)。

0 投票
1 回答
101 浏览

c# - 通过同步上下文自定义 MessageBox - 无法访问 Disposed 对象

我在这里的情况相当奇怪。我创建了一个自定义 MessageBox 表单(而不是内置的MessageBox.Show)。下面的代码是我在需要时用来调用表单的代码:

当我运行它时,我收到一条错误消息,messageBox.ShowDialog();表明 messageBox 实例已被释放。

当我将代码发布到同步上下文时,我很确定 MainForm 会运行代码本身(而不是其他线程),但我不确定它为什么告诉我 messageBox 已经被释放。

有任何想法吗?

0 投票
1 回答
515 浏览

c# - Synchronization.Context 在 Post 上为空,但在 Send 上不为空

我正在尝试对使用 Prism 事件聚合器的应用程序中的某些行为进行单元测试。我尝试进行单元测试的代码的其中一件事是订阅 UI 线程上的事件。深入研究 EventAggregator 的实现,我发现它是通过SynchronizationContext.Post.

我认为这个答案可能是一个很好的解决方法,但我最终使用了一个更简单的修复:在单元测试开始时显式设置同步上下文 - 在您尝试阅读之前一直有效SynchronizationContext.Current

这导致我产生一种我不完全理解的行为:

我知道 Post 是异步发生的,而 Send 是同步发生的,当我在线程调试窗口中观看它时,它实际上会跳转到不同的线程 ID,正如您期望异步调用所做的那样。

我想我想了解的是,当我告诉同步上下文执行一个函数时,无论是同步还是异步,我都希望该上下文被保留。它保留用于同步调用,但不用于异步。

为什么会出现这种行为,如何在单元测试中对其进行补偿?

0 投票
1 回答
462 浏览

c# - Task.Yield() 后 SynchronizationContext 丢失

我在线程之间传递文化时遇到了问题。我已经设法使用同步上下文让它在某种程度上工作,但在我的代码的一部分中,我使用了 Task.Yield()。在这段代码之后,我的上下文丢失了,这意味着在此之后的所有后续等待/收益都不要使用我的自定义 SynchronizationContext。

我把它归结为一个非常简单的测试,我可以看到在我们的 Task.Yield 之后,我们的 SynchronizationContext 丢失了。

同步上下文类:

单元测试 :

编辑:如果我使用新任务,如果我可以传入正确的 TaskScheduler,则上下文将被保留(尽管......它是调度程序,而不是同步上下文)。如以下:

0 投票
0 回答
836 浏览

c# - 如何从工作线程与 Microsoft.Owin 自托管 Web API 通信

我正在寻找有关如何从另一个线程与 Microsoft.Owin.Hosting.WebApp 实例进行通信的指导。

首先,我启动 Web 服务器和工作线程。IE。

现在我想在工作线程检测到事件时执行一些代码。此代码应与 Web 服务器和相同的 SynchronizationContext 运行在同一线程中(Web 应用程序完全是单线程和异步的)。我想以与 Web API 请求相同的异步方式处理这些事件,并能够在它们之间共享数据。

问题是上面的'app'只是IDisposable。我无法访问 WebAPI 请求的 SynchronizationContext。有没有办法以不同的方式实例化 Web 应用程序?

0 投票
1 回答
2310 浏览

c# - SynchronizationContext.Send 调用返回结果的 Func

我在当前项目中有一个简单的组件,可以从 Visual Studio 工具箱中拖放到 WinForms 应用程序中的 Forms 和 UserControls 上。

它按原样工作得很好 - 并且简单地包装了在 ISupportInitialize.BeginInit 期间捕获的 SynchronizationContext 的 Send 和 Post 方法(拥有 Form/Control 的 UI 上下文)。

这是最简单形式的组件的现有代码。

我现在需要扩展它以支持返回值,并且正在研究各种方式......

我有兴趣了解以下 3 种处理方式的含义,以及是否有“更好”的方式。

注意:我使用的示例是调用一个接受 1 个参数 arg1 并返回的函数TResult,即Func<T1, TResult>. 一旦我知道了最好的方法,我打算扩展它,所以我有可能覆盖Func<TResult>9args 的重载Func<T1,T2....T9,TResult>,以及Action重载。

Send0:第一种方式 - 是我已经在做的简单扩展:

Send1:第二种方式 - 是由对此的研究提示并查看有关 stackoverflow 的其他信息,这暗示我可能应该通过使用状态 arg 来获得结果。我想如果是这样的话——我可能也需要对输入参数做同样的事情,所以我得到了以下信息:

Send2:第三次尝试——我想既然我传递了参数,也许我也应该传递 Func 本身?无论如何 - 我得到了以下信息:

因此,我将其放入一个小型测试应用程序中,并从更新 WinForms 控件的后台线程测试每个方法,并对每个方法的 10k 次迭代进行了一些 Stopwatch 以测试各种方法的速度(仅使用字符串作为参数和返回值)他们都工作得很好,并且在那个简单的测试中具有相同的性能。不过,不确定使用非平凡的输入/输出类型会是什么样子。

那么 - Send0 好吗 - 其余的只是无关紧要/无缘无故的混乱?或者我应该考虑其中一个 - 还是别的什么?

0 投票
1 回答
45 浏览

c# - SynchronizationContext - 奇怪的行为

这段代码工作正常。我得到了源代码MessageBox。但是,为什么我在使用时会出现死锁var task = GetSource3()?我认为它必须有效,因为我使用ConfigureAwait(false)并避免了上下文切换