SetSynchronizationContext的生存期是多长?

问题描述

我有一个自定义SynchronizationContext,它抽象了一个自定义工作队列系统。我正在尝试编写一个帮助程序功能,以使客户端代码可以轻松为其编写代码。

我的助手功能当前如下:

void async Task QueueTaskWithCustomContext(Func<Task> task) {
  var oldContext = SynchronizationContext.Current;
  try {
    SynchronizationContext.SetCurrent(new CustomSynchronizationContext());
    // Yielding prevents any inline synchronous work from being done outside the work queue.
    await Task.Yield();
    await task();
  } finally {
    SynchronizationContext.SetCurrent(oldContext);
  }
}

我希望像这样使用

await QueueTaskWithCustomContext(async() => {
  await Something();
  await SomethingElse();
});

我不知道这是不是犹太洁食,但它似乎适用于我抛出的测试用例。我对如何设置同步上下文以及它如何与异步代码交互感到有些紧张。特别是,在任何情况下,自定义同步上下文都可以“泄漏”到辅助功能之外并为其他任务设置吗?我在想是否不立即等待助手功能。经过一些快速实验后,我无法实现它,但是我仍然很紧张。

或者,即使在第一次等待之后,我设置try / finally块的方式是否也可以保证设置同步上下文?再说一次,我无法通过快速实验来实现它,但是我仍然对此感到紧张。

我想我不太了解设置SynchronizationContext的生命周期。是永久设置,还是直到取消设置,还是仅针对当前功能或...设置?

解决方法

特别是,在任何情况下,自定义同步上下文可能会“泄漏”到辅助功能之外,并为其他任务设置吗?

绝对:

QueueTaskWithCustomContext(async() => await Task.Delay(1000));
await Task.Delay(10);

较小的延迟将在您的自定义调度程序上运行,而不是默认调度程序上。

我全心全意地建议您不要使用这种退化的代码,您会给用户带来麻烦,除了任务调度程序会突然发生意外更改之外,还会使用户感到惊讶。

编辑:由于我没有明确回答您的主要问题,因此“当前”任务调度程序的生命周期就是线程的生命周期。它存储在TLS中,因此只要您的线程存在,它就会存在。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...