问题标签 [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.
c# - 比较 SynchronizationContext
如何比较 SynchronizationContext?似乎同一个 Dispatcher 在使用 BeginInvoke 时可以创建不同的 SynchronizationContext。当我深入研究两个(不相等的)上下文时,我看到调度程序线程 ID 相同,但它们彼此不相等。
也许他们两个不能一起使用。我注意到这实际上有效:
更新但奇怪的是,它并不总是有效。
例如,永远不会得到匹配的 _context 并永远持续下去。即使它不应该。后一个示例线程实际上最终是相同的,并且有一个上下文,但它是不同的。
Update2好的,我让它工作了,但我真的对此感到不舒服。显然,当您发布或发送时,您的任务是从正确的线程运行的,但如果您不是来自 UI,似乎会生成一个新的 SynchronizationContext。
看看这个:
“需要直接调用者完全信任。部分信任或透明代码不能使用此成员。” :(
c# - 为什么发送到 WindowsFormsSynchronizationContext 时会动态调用 SendOrPostCallback 委托?
我正在编写一个允许我调用任意方法的包装器,SynchronizationContext
例如,允许我将与网络相关的回调(例如Socket.BeginReceive
)排队到某个任意调度程序/处理程序,例如 UI 线程,或者我自己的为串行执行而设计的实现. (以避免需要同步数据结构 - 锁等)。
基本上是这样的:
一切似乎都可以正常工作,WindowsFormsSynchronizationContext
但是当抛出异常时(A System.Reflection.TargetInvocationException
)我意识到SendOrPostCallback
委托正在被动态调用(?!)这是System.Windows.Forms.Control.ThreadMethodEntry
类中的相关代码(Microsoft Reference):
似乎不支持SendOrPostCallback
委托,但有趣的是它的签名与WaitCallback
! 或更一般地,一个Action<Object>
. 这让我产生疑问,我在这里做错了吗?还是这是设计使然?(我的意思是在语言和框架级别上......)。显然.. 动态调用所有已调度的方法调用会明显更慢且更难以调试?(到了我什至可能找不到可用的解决方案的地步?)。我在这里想念什么?
c# - 如何使用特定的调度程序(例如 GUI)启动任务
我正在尝试Task
使用 TPL 创建一个。例如:
这工作正常,但现在我想在 gui 线程上启动它。
我可以使用以下命令缓存 gui 调度程序:
但我看不到如何使用此调度程序启动新任务。一旦初始任务完成,我可以找到的所有示例都Task.ContinueWith()
用于安排第二个任务_uiScheduler
,但我想使用此调度程序创建初始任务。
干杯
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
的调用可能会死锁。.Result
MyWebMethod
因为我不会“一直异步”,所以这是一个“同步异步”场景。根据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
实现,但这会涉及我宁愿花在更紧迫问题上的开发时间(如果可能的话)。另外,我仍然想弄清楚不同TaskScheduler
和TaskCreationOptions
场景发生了什么。
我巧合地发现,TaskCreationOptions.PreferFairness
在 .NET 4.0 中似乎表现得如我所愿(所有执行都有一个空同步上下文),但不知道为什么会这样,我很犹豫要不要使用它(它可能无法正常工作)情景)。
编辑
一些额外的信息...我已经用一个死锁的代码更新了我的示例代码,并包含一些调试输出以显示任务正在运行的线程。如果 pre-task 或 continuation-task 输出指示与 WebMethod 相同的线程 id,则会发生死锁。
奇怪的是,如果我不使用 ProgressMessageHandler,我似乎无法复制死锁。我的印象是这无关紧要,无论下游代码如何,我都应该能够使用正确的Task.Factory.StartNew
或方法在同步上下文中安全地“包装”异步Task.Run
方法。但这似乎并非如此?
c# - Task.ContinueWith(..., TaskScheduler.FromCurrentSynchronizationContext()) *不会*在 UI 线程上运行的任何场景?
我们正在观察一些奇怪的东西,代码如下:
那里的第二个任务调用一个事件,该事件反过来尝试更新 GUI,我们得到了可怕的跨线程异常。
从第二个任务中的方法检查Thread.CurrentThread.ManagedThreadId
表明它实际上没有在 UI 线程上运行。
生成任务的代码在 UI 线程上运行。
是否有任何情况会出错?
c# - 主线程终止时 SynchronizationContext 会发生什么?
我有两个线程,主线程和我创建的另一个线程来做一些工作。我不明白当我从另一个线程调用 originalContext.Post(主线程的同步上下文)时会发生什么,其中一些 UI 元素已更新,而主线程已经终止?这安全吗?为什么?
提前致谢。
c# - 使用 c#5.0 调用异步方法
我使用 C# 5.0 (async/await) 的新异步模式进行了一些测试,但我在理解如何调用异步方法时遇到了问题。
考虑到这段代码:
所以,这段代码工作得很好。当我单击“button4”时,下载任务开始并且我的 ProgressBar 已正确更新。
但是,我想通过删除这样的 CallDownloadAsync() 方法来进一步压缩我的代码:
所以在这里,我想直接启动一个调用 DownloadAsync 方法的操作,但是当我点击我的 Button4 时,我的跨线程操作在进度条上无效。所以我不明白 Action() 和我的 CallDownloadAsync() 方法的调用之间的主要区别是什么。
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 在实例化表单时隐式更改行为)。
c# - 书中的短语“当前 SynchronizationContext 是当前线程的属性”是否正确?
读过“当前 SynchronizationContext 是当前线程的属性”正确的短语后,我有点困惑......
在 VS2010 的 C# 应用程序代码中,当我键入时,我Thread.CurrentThread.
在 Intellisense 给出的选项下拉列表中找不到线程的任何上下文相关属性。
我知道当前的同步上下文可以通过 " = SynchronizationContext.Current;
" 获得。但这对于在并行线程、任务等中同时执行并不是很幸运。
假设从控制台或 WPF (*)应用程序中,我在其自己的主 UI 线程以及 TPL 任务 中创建并启动了一些 Windows 窗体。
我认为每个winform都应该有自己的WindowsFormaSynchronizationContext,WPF 应该有自己的DispatcherSynchronizationContext(SynchronizationContext 类的子类)实例,任务在具有自己的同步上下文的ThreadPool中执行, LongRunning 任务或者可能会在其线程池中执行自己的同步上下文...
那么,为什么不能SynchronizationContext
从线程中定义呢?“从给定线程获取 SynchronizationContext”问题的所有答案似乎都在否定这种可能性......
最后但并非最不重要的一点是:“当前 SynchronizationContext 是当前线程的属性”
这句话是否正确?
那么,我如何才能为不同的特定线程实例获取此属性的值?
(*)
最近,我收到了基本上使用 winforms 的 C# WPF 应用程序代码。
c# - 使用 TaskScheduler 的最佳方式
我的应用程序偶尔崩溃,这是因为在应用程序加载后我调用TaskScheduler.FromCurrentSynchronizationContext()
的速度太快了。
通过一些测试,我已经使用 readonlyTaskScheduler
字段解决了这个问题,并将其填充到类的构造函数中(感谢另一个 SO 答案),但我担心TaskScheduler
由于应用程序的大小和对TaskScheduler
.
有没有人A)在构造函数中从调用更改TaskScheduler.FromCurrentSynchronizationContext()
为实例化单个实例并且B)成功了?