问题标签 [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 对象在 UI 线程上运行任务的示例:
我可以在一个新项目中重复这些结果,安全地更新 UI,但是在我当前的项目中(即使它一直在工作)我不能。我得到标准的“您不允许从错误的线程更新 UI”异常。
我的代码(在 MainForm_Load(...) 中)是这样的,它在一个新的项目中工作,并在主窗体中添加了一个 textBox1,但在我当前的项目中不起作用:
任何人都对可能发生的事情有任何想法。
[编辑]
我将错误追溯到使用表单提示用户输入登录信息的对象的实例化。该错误仅在显示表单时发生。(如果我在该表单Show
发生之前返回一个硬编码值,则整个事情都可以正常工作)。
新问题:如果它自己的构造函数在显示另一个表单之前显示另一个表单,我如何获得我正在构建的表单的 SynchronizationContext?以下是如何重现正在发生的事情:
1) 创建两个表单: Form1 和 a TextBox
, Form2 和 aButton
2)创建一个类OwnedBy1Uses2
Form1
:
Form2
:
OwnedBy1Uses2
:
c# - 何时在 UI 应用程序中调用 SynchronizationContext.SetSynchronizationContext()?
我正在学习这SynchronizationContext
门课。我试图了解SynchronizationContext.SetSynchronizationContext()
在 WinForm/WPF 应用程序的上下文中调用的常见使用场景是什么。SynchronizationContext
设置线程的 是什么意思?我应该什么时候做,为什么?另外,如果我设置它,我应该在某个时候取消它吗?
编辑:
在他的回答中,@Hans Passant 问我为什么要考虑SetSynchronizationContext()
。我的想法是在工作线程上设置上下文,以便在该线程上运行的代码将具有要使用的上下文。
.net - .NET:如何在特定线程上调用委托?(ISynchronizeInvoke、Dispatcher、AsyncOperation、SynchronizationContext 等)
首先请注意,此问题未标记为winforms或wpf或任何其他特定于 GUI 的内容。这是有意的,你很快就会看到。
其次,对不起,如果这个问题有点长。我试图将到处飘荡的各种信息汇集在一起,以提供有价值的信息。然而,我的问题就在“我想知道的”下面。
我的任务是最终了解 .NET 提供的在特定线程上调用委托的各种方法。
我想知道的:
我正在寻找最通用的方式(不是 Winforms 或 WPF 特定的)来调用特定线程上的委托。
或者,换种说法:我会感兴趣,如果以及如何,不同的方式来做到这一点(例如通过 WPF's
Dispatcher
)相互利用;也就是说,如果所有其他人都使用一种通用的跨线程委托调用机制。
我已经知道的:
有很多与这个主题相关的课程;其中:
SynchronizationContext
(inSystem.Threading
)
如果我不得不猜测,那将是最基本的一个;虽然我不明白它到底是做什么的,也不知道它是如何使用的。AsyncOperation
& (in ) 这些似乎是. 不知道如何使用它们。AsyncOperationManager
System.ComponentModel
SynchronizationContext
WindowsFormsSynchronizationContext
(inSystem.Windows.Forms
)
的子类SynchronizationContext
。ISynchronizeInvoke
(inSystem.ComponentModel
)
由 Windows 窗体使用。(Control
该类实现了这一点。如果我不得不猜测,我会说这个实现使用了WindowsFormsSynchronizationContext
.)Dispatcher
& (in ) 似乎后者是 的另一个子类,而前者代表它。DispatcherSynchronizationContext
System.Windows.Threading
SynchronizationContext
一些线程有自己的消息循环以及消息队列。
(关于消息和消息队列的 MSDN 页面有一些关于消息循环如何在系统级别工作的介绍性背景信息,即作为 Windows API 的消息队列。)
我可以看到如何为带有消息队列的线程实现跨线程调用。
PostThreadMessage
使用 Windows API,您可以通过包含调用某个委托的指令将消息放入特定线程的消息队列中。在该线程上运行的消息循环最终将获得该消息,并且将调用委托。根据我在 MSDN 上阅读的内容,线程不会自动拥有自己的消息队列。例如,当一个线程创建了一个窗口时,一个消息队列将变得可用。没有消息队列,线程有消息循环是没有意义的。
那么,当目标线程没有消息循环时,是否可以进行跨线程委托调用?比方说,在 .NET 控制台应用程序中?(从这个问题的答案来看,我想控制台应用程序确实不可能。)
wpf - WPF + 任务 + WCF = 没有 SynchronizationContext?
我有一个 WPF 应用程序,它使用 System.Threading.Tasks 在后台调用 WCF 服务。我正在使用 Task.ContinueWith 将服务调用的结果返回给 WPF UI 线程。我的问题是,虽然延续确实在 UI 线程上运行,但当它运行时 SynchronizationContext.Current 为空。我可以运行相同的代码,在初始任务中注释掉 WCF 调用,并且继续在 UI 线程上,并按预期使用 DispatcherSynchronizationContext。
WCF 代理使用 ChannelFactory 生成,并使用 wsHttpBinding。没有回调合约。相关代码如下所示:
如果我按原样运行此代码,则会在正确的线程上调用 ServiceContinuation(使用 ManagedThreadID 进行验证),但 SynchronizationContext.Current 为空。如果我注释掉进行服务调用的单行 (result = service.TheServiceMethod();),则使用 DispatcherSynchronizationContext 正确调用 ServiceContinuation。
请注意 - SynchronizationContext 不会永久丢失 - 如果我再次单击按钮,则按钮单击处理程序确实具有正确的 SynchronizationContext。
我已经捕获了这两种情况的堆栈跟踪;他们有一些不同之处。我省略了所有相同的位,只包括它们不同的堆栈顶部,以及一些参考帧:
失败 - 调用 WCF 服务
成功 - 不调用 WCF 服务
有谁知道为什么,当唯一的区别是 WCF 客户端服务调用(没有回调合同)时,在一种情况下,主线程上的延续会具有 SynchronizationContext,而在另一种情况下则不会?
c# - SynchronizationContext 和 InvokeRequired
我一直在寻找这个问题的答案,但似乎找不到令人满意的答案。也许这里有人可以启发我。
我有一个BindingList<T>
存储对对象的引用的后代,SynchronizationContext
以便在 UI 线程上引发其更改的事件。
现在,它也有可能BindingList<T>
是在 UI 线程而不是后台线程上创建和使用的。如果没有类似可用的属性,我该如何检查InvokeRequired
?SynchronizationContext.Send
在 UI 线程上调用会有什么后果?
c# - 为什么 TaskScheduler.Current 是默认的 TaskScheduler?
Task Parallel Library 很棒,在过去的几个月里我经常使用它。但是,有一些事情真的让我很困扰:这TaskScheduler.Current
是默认任务调度程序,而不是TaskScheduler.Default
. 乍一看,这在文档或示例中绝对不明显。
Current
可能会导致细微的错误,因为它的行为会根据您是否在另一个任务中而改变。哪个不容易确定。
假设我正在编写一个异步方法库,使用基于事件的标准异步模式在原始同步上下文上发出信号完成信号,就像 XxxAsync 方法在 .NET Framework 中所做的一样(例如DownloadFileAsync
)。我决定使用任务并行库来实现,因为用下面的代码很容易实现这个行为:
到目前为止,一切正常。现在,让我们在 WPF 或 WinForms 应用程序中单击按钮时调用此库:
Task
在这里,编写库调用的人选择在操作完成时开始新的调用。没有什么不寻常的。他或她遵循网络上随处可见的示例,并且Task.Factory.StartNew
无需指定即可简单地使用TaskScheduler
(并且在第二个参数处指定它并不容易重载)。该DoSomethingElse
方法在单独调用时工作正常,但一旦被事件调用,UI 就会冻结,因为TaskFactory.Current
将重用我的库延续中的同步上下文任务调度程序。
找出这可能需要一些时间,特别是如果第二个任务调用被埋在一些复杂的调用堆栈中。当然,一旦你知道一切是如何工作的,这里的修复很简单:总是TaskScheduler.Default
为你期望在线程池上运行的任何操作指定。但是,也许第二个任务是由另一个外部库启动的,不知道这种行为并且StartNew
在没有特定调度程序的情况下天真地使用。我预计这种情况会很普遍。
在把我的脑袋绕过去之后,我无法理解编写 TPL 的团队选择使用TaskScheduler.Current
而不是TaskScheduler.Default
作为默认值:
- 一点都不明显,
Default
不是默认的!而且文档严重缺乏。 - 真正使用的任务调度器
Current
依赖于调用栈!这种行为很难保持不变量。 - 指定任务调度程序很麻烦,
StartNew
因为您必须首先指定任务创建选项和取消令牌,导致行长、可读性差。这可以通过编写扩展方法或创建TaskFactory
使用Default
. - 捕获调用堆栈会带来额外的性能成本。
- 当我真的希望一个任务依赖于另一个正在运行的父任务时,我更愿意明确指定它以简化代码阅读,而不是依赖调用堆栈魔术。
我知道这个问题听起来可能很主观,但我找不到一个好的客观论据来解释为什么这种行为会如此。我确定我在这里遗漏了一些东西:这就是我转向你的原因。
winforms - 如何在 WinForm 线程上获取 WinForm 同步上下文或调度
我有一个 winform 应用程序,以及一个像这样的 observable 设置:
这不起作用,因为l => lb.Text = l.ToString()
不会在创建表单的主线程上运行,但我不知道如何让它在这个线程上运行。我假设我应该使用IObservable.SubscribeOn
which 需要 anIScheduler
或 a SynchronizationContext
,但我不知道如何获取主线程的同步上下文,并且我能找到的唯一调度程序是 的静态属性,Scheduler
例如Scheduler.CurrentThread
, Immediate
,和NewThread
,没有一个奏效。TaskPool
ThreadPool
我的 Rx 版本是 1.0.10621。
c# - 当没有更多可用线程时,是否会阻塞 .ForEach 循环
我们有一个.ForEach
循环(TPL),它启动了很多很多任务。由于 TPL 正在使用线程池中的线程,我想知道当没有更多可用线程时会发生什么?调用代码是否会阻塞,直到线程再次可用?
我知道线程池有一个全局工作队列,工作项 ( Task
) 将在其中排队。那个队列能满吗?
我们的问题是有些任务运行时间很长(30 分钟),有些任务很短(一秒钟),但我们有成千上万个这样的任务,如果不是更多的话。TPL 是否为我启动的每个任务启动一个新线程?我想不是。线程池什么时候会耗尽?
c# - 获取 TaskScheduler/SynchronizationContext 以在特定线程上执行
考虑 WPF ViewModel 的以下代码:
... 其中 modelChanged 是一个事件处理程序,用于响应对象模型中的更改。此代码在 UI 线程上执行,旨在希望在 UI 线程上处理事件,而不管它们是从哪个线程触发的。
但是,当它运行时,输出类似于:
我的期望是线程 1 将是所有处理发生的地方。即使我尝试像这样直接使用 SynchronizationContext :
...我看到同样的事情。
我的想法或方法有问题吗?如何在 init 线程上处理要处理的事件?
提前致谢!
c# - 像线程编组这样的框架
我一直认为我可以使用 SynchronizationContext 来编组对另一个线程的调用。显然我错了,因为 SyncCtx.Send() 除了调用给定的委托(保持在同一个线程上)之外什么都不做。我真的需要从 SynchronizationContext 派生并在线程上下文上工作吗?我感觉好像错过了什么。
我想要实现的目标:想象一个用于在应用程序中执行命令的小 API。您还可以在后台线程上执行命令,因为您可以分配一个委托以在命令完成执行时运行。这个“Call-me-when-done”-Delegate 获得一个包含成功/失败标志、可选异常信息等的单个参数(状态)。我想在原始调用线程上调用这个委托,这样使用 lib 的开发人员就不会需要处理所需的调用等。我只想把它拿走,让他们做简单的非线程感知编程。如果您不给它一些控制作为目标,WindowsFormsSynchronizationContext 似乎也无济于事。
谢谢你的帮助!