Custom TaskFactory不使用自定义SynchronizationContext

问题描述 投票:0回答:2

我需要使用自定义同步上下文运行内部任务,如下所示:

  • 外部任务->在默认计划程序上
    • 内部任务->具有自定义同步上下文的自定义调度程序上的>]
  • 这是因为内部任务中的某些对象只能在自定义同步上下文将发布到的特定线程上创建,另一方面,我希望外部任务正常运行,即ThreadPool或任何[C0 ]使用。

遵循以下问题的建议:

Task.Run

不幸的是,这不起作用,同步上下文仍然是默认上下文:

How to run a Task on a custom TaskScheduler using await?

代码:

OUTER JOB: 'null'
0
        INNER JOB: 'null' <------------- this context should not be the default one
        0,      1,      2,      3,      4,
1
        INNER JOB: 'null'
        0,      1,      2,      3,      4,
2
        INNER JOB: 'null'
        0,      1,      2,      3,      4,
Done, press any key to exit

[调试时,我可以看到定制工厂确实具有带有定制上下文的定制调度程序,但是实际上它不起作用。

问题:

我如何让我的自定义计划程序使用从其创建的自定义上下文?

我需要使用自定义同步上下文来运行内部任务,如下所示:外部任务->默认调度程序上的内部任务->在具有自定义同步上下文的自定义调度程序上此...

c# asynchronous task-parallel-library synchronizationcontext
2个回答
0
投票
您的using System; using System.Threading; using System.Threading.Tasks; internal static class Program { private static TaskFactory CustomFactory { get; set; } private static async Task Main(string[] args) { // create a custom task factory with a custom synchronization context, // and make sure to restore initial context after it's been created var initial = SynchronizationContext.Current; SynchronizationContext.SetSynchronizationContext(new CustomSynchronizationContext()); CustomFactory = new TaskFactory( CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext() ); SynchronizationContext.SetSynchronizationContext(initial); // now do some work on initial context await Task.Run(async () => { Console.WriteLine($"OUTER JOB: {GetCurrentContext()}"); for (var i = 0; i < 3; i++) { Console.WriteLine(i); await Task.Delay(100); // now do some work on custom context await RunOnCustomScheduler(DoSpecialWork); } }); Console.WriteLine("Done, press any key to exit"); Console.ReadKey(); } private static void DoSpecialWork() { Console.WriteLine($"\tINNER JOB: {GetCurrentContext()}"); // TODO wrong context for (var i = 0; i < 5; i++) { Thread.Sleep(250); Console.Write($"\t{i}, "); } Console.WriteLine(); } private static Task RunOnCustomScheduler(Action action) { return CustomFactory.StartNew(action); } private static string GetCurrentContext() { return SynchronizationContext.Current?.ToString() ?? "'null'"; } } public class CustomSynchronizationContext : SynchronizationContext { } 实际上用于运行CustomSynchronizationContext方法。您可以通过重写基类的DoSpecialWork方法来确认这一点:

-1
投票
您可以使用ReactiveExtensions(nuget System.Reactive)轻松实现这一目标:
© www.soinside.com 2019 - 2024. All rights reserved.