问题标签 [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 投票
1 回答
1847 浏览

c# - 比较 SynchronizationContext

如何比较 SynchronizationContext?似乎同一个 Dispatcher 在使用 BeginInvoke 时可以创建不同的 SynchronizationContext。当我深入研究两个(不相等的)上下文时,我看到调度程序线程 ID 相同,但它们彼此不相等。

也许他们两个不能一起使用。我注意到这实际上有效:

更新但奇怪的是,它并不总是有效。

例如,永远不会得到匹配的 _context 并永远持续下去。即使它不应该。后一个示例线程实际上最终是相同的,并且有一个上下文,但它是不同的。

Update2好的,我让它工作了,但我真的对此感到不舒服。显然,当您发布或发送时,您的任务是从正确的线程运行的,但如果您不是来自 UI,似乎会生成一个新的 SynchronizationContext。

看看这个:

在此处输入图像描述

“需要直接调用者完全信任。部分信任或透明代码不能使用此成员。” :(

0 投票
1 回答
1098 浏览

c# - 为什么发送到 WindowsFormsSynchronizationContext 时会动态调用 SendOrPostCallback 委托?

我正在编写一个允许我调用任意方法的包装器,SynchronizationContext例如,允许我将与网络相关的回调(例如Socket.BeginReceive)排队到某个任意调度程序/处理程序,例如 UI 线程,或者我自己的为串行执行而设计的实现. (以避免需要同步数据结构 - 锁等)。

基本上是这样的:

一切似乎都可以正常工作,WindowsFormsSynchronizationContext但是当抛出异常时(A System.Reflection.TargetInvocationException)我意识到SendOrPostCallback委托正在被动态调用(?!)这是System.Windows.Forms.Control.ThreadMethodEntry类中的相关代码(Microsoft Reference):

似乎不支持SendOrPostCallback委托,但有趣的是它的签名与WaitCallback! 或更一般地,一个Action<Object>. 这让我产生疑问,我在这里做错了吗?还是这是设计使然?(我的意思是在语言和框架级别上......)。显然.. 动态调用所有已调度的方法调用会明显更慢且更难以调试?(到了我什至可能找不到可用的解决方案的地步?)。我在这里想念什么?

0 投票
3 回答
292 浏览

c# - 如何使用特定的调度程序(例如 GUI)启动任务

我正在尝试Task使用 TPL 创建一个。例如:

这工作正常,但现在我想在 gui 线程上启动它。

我可以使用以下命令缓存 gui 调度程序:

但我看不到如何使用此调度程序启动新任务。一旦初始任务完成,我可以找到的所有示例都Task.ContinueWith()用于安排第二个任务_uiScheduler,但我想使用此调度程序创建初始任务。

干杯

0 投票
1 回答
2078 浏览

asp.net - 对异步同步的 TaskScheduler 和 SynchronizationContext 感到困惑,无法控制同步上下文?

问题

我有一个带有简单 web-service 的 ASP.NET 4.0 WebForms 页面WebMethod。此方法用作异步/TPL 代码的同步包装器。我面临的问题是内部Task有时有一个空值SynchronizationContext(我的偏好),但有时有一个同步上下文System.Web.LegacyAspNetSynchronizationContext。在我提供的示例中,这并不会真正导致问题,但在我的实际开发场景中可能会导致死锁。

对服务的第一次调用似乎总是使用空同步上下文运行,接下来的几个也可能如此。但是一些快速请求,它开始弹出到 ASP.NET 同步上下文中。

编码

存在的定义TaskHolder

分析

我的理解TaskScheduler.Default是它是ThreadPool调度程序。换句话说,线程不会在 ASP.NET 线程上结束。根据这篇文章“任务并行库和 PLINQ 的默认调度程序使用 .NET Framework 线程池来排队和执行工作”。基于此,我希望SynchronizationContext内部SampleTask始终为空。

此外,我的理解是,如果SampleTask要在 ASP.NET 上,对inSynchronizationContext的调用可能会死锁。.ResultMyWebMethod

因为我不会“一直异步”,所以这是一个“同步异步”场景。根据Stephen Toub 的这篇文章,在标题为“如果我真的需要“同步而不是异步”怎么办?以下代码应该是一个安全的包装器:

根据同样由 Stephen Toub 撰写的另一篇文章,上述内容在功能上应等同于:

由于在 .NET 4.0 中,我无法访问TaskCreationOptions.DenyChildAttach,我认为这是我的问题。但是我在 .NET 4.5 中运行了相同的示例并切换到TaskCreationOptions.DenyChildAttach它,它的行为相同(有时会抓取 ASP.NET 同步上下文)。

然后我决定更接近“原始”建议,并在 .NET 4.5 中实现:

确实有效,因为它总是有一个空同步上下文。哪一种暗示Task.Run 与 Task.Factory.StartNew 文章有问题?

务实的方法是升级到 .NET 4.5 并使用Task.Run实现,但这会涉及我宁愿花在更紧迫问题上的开发时间(如果可能的话)。另外,我仍然想弄清楚不同TaskSchedulerTaskCreationOptions场景发生了什么。

我巧合地发现,TaskCreationOptions.PreferFairness在 .NET 4.0 中似乎表现得如我所愿(所有执行都有一个空同步上下文),但不知道为什么会这样,我很犹豫要不要使用它(它可能无法正常工作)情景)。

编辑

一些额外的信息...我已经用一个死锁的代码更新了我的示例代码,包含一些调试输出以显示任务正在运行的线程。如果 pre-task 或 continuation-task 输出指示与 WebMethod 相同的线程 id,则会发生死锁

奇怪的是,如果我不使用 ProgressMessageHandler,我似乎无法复制死锁。我的印象是这无关紧要,无论下游代码如何,我都应该能够使用正确的Task.Factory.StartNew或方法在同步上下文中安全地“包装”异步Task.Run方法。但这似乎并非如此?

0 投票
1 回答
2180 浏览

c# - Task.ContinueWith(..., TaskScheduler.FromCurrentSynchronizationContext()) *不会*在 UI 线程上运行的任何场景?

我们正在观察一些奇怪的东西,代码如下:

那里的第二个任务调用一个事件,该事件反过来尝试更新 GUI,我们得到了可怕的跨线程异常。

从第二个任务中的方法检查Thread.CurrentThread.ManagedThreadId表明它实际上没有在 UI 线程上运行。

生成任务的代码在 UI 线程上运行

是否有任何情况会出错?

0 投票
1 回答
179 浏览

c# - 主线程终止时 SynchronizationContext 会发生什么?

我有两个线程,主线程和我创建的另一个线程来做一些工作。我不明白当我从另一个线程调用 originalContext.Post(主线程的同步上下文)时会发生什么,其中一些 UI 元素已更新,而主线程已经终止?这安全吗?为什么?

提前致谢。

0 投票
2 回答
1049 浏览

c# - 使用 c#5.0 调用异步方法

我使用 C# 5.0 (async/await) 的新异步模式进行了一些测试,但我在理解如何调用异步方法时遇到了问题。

考虑到这段代码:

所以,这段代码工作得很好。当我单击“button4”时,下载任务开始并且我的 ProgressBar 已正确更新。

但是,我想通过删除这样的 CallDownloadAsync() 方法来进一步压缩我的代码:

所以在这里,我想直接启动一个调用 DownloadAsync 方法的操作,但是当我点击我的 Button4 时,我的跨线程操作在进度条上无效。所以我不明白 Action() 和我的 CallDownloadAsync() 方法的调用之间的主要区别是什么。

0 投票
2 回答
1921 浏览

winforms - 如果存在 System.Windows.Forms.Form 实例,则等待 Task.Delay(...) 冻结

DoTheStuff().Wait();如果作为控制台应用程序运行,则以下程序挂起:

如果您注释掉该new Form();行,它会按预期工作。(运行 1 秒,然后退出)。 我怎样才能保持预期的行为并且仍然有一个 Form 实例?

现在,如果您有兴趣,请提供一些背景知识:

我有一个作为 Windows 服务托管的应用程序(在本地测试时作为控制台)。

它需要有权访问该SystemEvents.TimeChanged事件。

但是,根据文档,这仅在具有 Windows 窗体时有效(因此不适用于服务或控制台应用程序)。链接文档中提供了一种解决方法,包括创建隐藏表单。

不幸的是,程序现在完全冻结了,这是由 await 和拥有Form实例的组合引起的。

那么在访问SystemEvents.TimeChanged事件时,我到底如何才能拥有预期的异步/等待行为呢?


感谢下面的帮助,这里有修改后的代码,它可以在没有冻结的情况下工作:

在我的程序中,我需要使用“SynchronizationContext.SetSynchronizationContext(null);”,因为线程池应该用于等待任务。我认为这不是一个好习惯,因为 Form 显然是出于某种原因对其进行了初始化。但是在没有用户输入的情况下运行隐藏的表单(它是一项服务!),现在看不到任何伤害。

文档感觉有点不完整,MS 甚至没有提到使用示例 2 可能出现的问题(await/async 在实例化表单时隐式更改行为)。

0 投票
1 回答
410 浏览

c# - 书中的短语“当前 SynchronizationContext 是当前线程的属性”是否正确?

读过“当前 SynchronizationContext 是当前线程的属性”正确的短语后,我有点困惑......

在 VS2010 的 C# 应用程序代码中,当我键入时,我Thread.CurrentThread.在 Intellisense 给出的选项下拉列表中找不到线程的任何上下文相关属性。

我知道当前的同步上下文可以通过 " = SynchronizationContext.Current;" 获得。但这对于在并行线程、任务等中同时执行并不是很幸运。

假设从控制台或 WPF (*)应用程序中,我在其自己的主 UI 线程以及 TPL 任务 中创建并启动了一些 Windows 窗体。

我认为每个winform都应该有自己的WindowsFormaSynchronizationContext,WPF 应该有自己的DispatcherSynchronizationContextSynchronizationContext 类的子类)实例,任务在具有自己的同步上下文的ThreadPool中执行, LongRunning 任务或者可能会在其线程池中执行自己的同步上下文...

那么,为什么不能SynchronizationContext从线程中定义呢?“从给定线程获取 SynchronizationContext”问题的所有答案似乎都在否定这种可能性......

最后但并非最不重要的一点是:“当前 SynchronizationContext 是当前线程的属性”
这句话是否正确? 那么,我如何才能为不同的特定线程实例获取此属性的值?

(*)
最近,我收到了基本上使用 winforms 的 C# WPF 应用程序代码。

0 投票
0 回答
137 浏览

c# - 使用 TaskScheduler 的最佳方式

我的应用程序偶尔崩溃,这是因为在应用程序加载后我调用TaskScheduler.FromCurrentSynchronizationContext()的速度太快了。

通过一些测试,我已经使用 readonlyTaskScheduler字段解决了这个问题,并将其填充到类的构造函数中(感谢另一个 SO 答案),但我担心TaskScheduler由于应用程序的大小和对TaskScheduler.

有没有人A)在构造函数中从调用更改TaskScheduler.FromCurrentSynchronizationContext()为实例化单个实例并且B)成功了?