我需要使用自定义同步上下文运行内部任务,如下所示:
这是因为内部任务中的某些对象只能在自定义同步上下文将发布到的特定线程上创建,另一方面,我希望外部任务正常运行,即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
[调试时,我可以看到定制工厂确实具有带有定制上下文的定制调度程序,但是实际上它不起作用。
问题:
我如何让我的自定义计划程序使用从其创建的自定义上下文?
我需要使用自定义同步上下文来运行内部任务,如下所示:外部任务->默认调度程序上的内部任务->在具有自定义同步上下文的自定义调度程序上此...
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
方法来确认这一点: