- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
假设您正在编写自定义单线程 GUI 库(或任何带有事件循环的库)。根据我的理解,如果我使用 async/await
,或者只是常规的 TPL 延续,它们将全部安排在 TaskScheduler.Current
(或 SynchronizationContext.Current
)。
问题是延续可能想要访问库的单线程部分,这意味着它必须在同一个事件循环中执行。例如,给定一个简单的游戏循环,事件可能会像这样处理:
// All continuation calls should be put onto this queue
Queue<Event> events;
// The main thread calls the `Update` method continuously on each "frame"
void Update() {
// All accumulated events are processed in order and the queue is cleared
foreach (var event : events) Process(event);
events.Clear();
}
现在假设我的假设是正确的并且 TPL 使用 SynchronizationContext.Current
,应用程序中的任何代码都应该能够执行如下操作:
async void Foo() {
someLabel.Text = "Processing";
await BackgroundTask();
// This has to execute on the main thread
someLabel.Text = "Done";
}
这让我想到了这个问题。 我如何实现自定义 SynchronizationContext
以允许我在自己的线程上处理延续?这是正确的方法吗?
最佳答案
实现自定义 SynchronizationContext
并不是世界上最简单的事情。我有一个开源单线程实现 here您可以将其用作起点(或者可能只是用来代替您的主循环)。
默认情况下,AsyncContext.Run
采用单个委托(delegate)来执行并在完全完成时返回(因为 AsyncContext
使用自定义 SynchronizationContext
,它能够等待 async void
方法以及常规的异步/同步代码)。
AsyncContext.Run(async () => await DoSomethingAsync());
如果您想要更大的灵 active ,您可以使用 AsyncContext
高级成员(它们不会出现在 IntelliSense 中,但它们在那里)来保持上下文事件直到某些外部信号(如“退出帧” "):
using (var context = new AsyncContext())
{
// Ensure the context doesn't exit until we say so.
context.SynchronizationContext.OperationStarted();
// TODO: set up the "exit frame" signal to call `context.SynchronizationContext.OperationCompleted()`
// (note that from within the context, you can alternatively call `SynchronizationContext.Current.OperationCompleted()`
// Optional: queue any work you want using `context.Factory`.
// Run the context; this only returns after all work queued to this context has completed and the "exit frame" signal is triggered.
context.Execute();
}
AsyncContext
的 Run
和 Execute
在运行时替换当前的 SynchronizationContext
,但它们保存原始上下文并在返回之前将其设置为当前上下文。这允许它们以嵌套方式(例如,“框架”)很好地工作。
(我假设“框架”是指一种类似于 WPF 的调度程序框架)。
关于c# - 如何创建自定义 SynchronizationContext 以便所有延续都可以由我自己的单线程事件循环处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39271492/
我仍在学习整个任务概念和 TPL。根据我目前的理解,await 使用 SynchronizationContext 函数(如果存在)将任务分派(dispatch)到“某处”。另一方面,Task 类中的
感谢 Jeremy Miller 在 Functional Programming For Everyday .NET Development 中的出色工作,我有一个工作命令执行器,它可以做我想做的一
我使用 SynchronizationContext从 UI 线程上的后台线程调用方法。我读了this post它要求 Send 的差异和 Post .我明白答案并会调用Send每当我需要调用方法的结
我遇到了挂起等待的问题(描述 here )。在研究过程中,我发现调用 SetResult在我的 TaskCompletionSource实际上在调用 SetResult 的线程的上下文中调用等待继续(
public static void Init() { //var task = GetSource1(); //var task = GetSource2(); //var
在异步函数内部使用与外部不同的 SynchronizationContext 时,我的行为令人困惑。 我的大部分程序代码都使用自定义 SynchronizationContext,它只是将 SendO
我正在尝试了解 SynchronizationContext 和 friend 。如果我在例如开始时设置自定义同步上下文控制台应用程序。在什么情况下当前同步上下文将与我的异步操作一起流动?Task 和
我想了解更多关于 SynchronizationContext 的信息,所以我制作了这个简单的控制台应用程序: private static void Main() { var sc = ne
我不知道如何获取给定 Thread 的 SynchronizationContext: Thread uiThread = UIConfiguration.UIThread; Synchronizat
如何比较 SynchronizationContext?似乎同一个 Dispatcher 在使用 BeginInvoke 时可以创建不同的 SynchronizationContext。当我深入研究两
在Programming C#一书中,它有一些关于SynchronizationContext的示例代码。 : SynchronizationContext originalContext = Syn
对于 WinForms 和 WPF,我使用 SynchronizationContext 作为同步到 GUI 线程的方法。最近我遇到了旧式异步回调的问题: private void Button
我有以下代码: [TestMethod] public void StartWorkInFirstThread() { if (SynchronizationContext.Current =
SynchronizationContext 有一个名为 IsWaitNotificationRequired 的属性.出于其目的,docs有话要说: Determines if wait notif
说,我有以下代码: IPrincipal capturedPrincipal = Thread.CurrentPrincipal; myseq.AsParallel().Select(x => {
这是一个非常基本的问题,我想是的,但是我找不到任何明确的答案。 SynchronizationContext.Post()线程安全吗? 我有一个成员变量,它保存主线程的上下文,并且从多个线程中调用_c
SynchronizationContext.Current 在主线程上为 null,我很难弄清楚这一点。 static class Program { /// //
我正在创建 SynchronizationContext 的 STA 版本以用于 Windows Workflow 4.0。我想知道在发布回调时如何处理异常。 SynchronizationConte
简而言之,我已经实现了一个派生自 SynchronizationContext 的类,以便 GUI 应用程序可以轻松地使用在 GUI 线程以外的线程上引发的事件。我非常感谢对我的实现的评论。具体来说,
我有两个线程,一个是主线程,另一个是我创建的线程来做一些工作。我不明白当我从另一个线程调用 originalContext.Post(主线程的 SyncronizationContext)时会发生什么
我是一名优秀的程序员,十分优秀!