【发布时间】:2021-09-17 10:52:05
【问题描述】:
我希望在自定义线程池上执行一堆 ValueTask-returning 函数 - 即在我自己生成和处理的一堆线程上,而不是默认的 ThreadPool。
意思是,这些函数的所有同步位,包括任何潜在的任务延续,都应该在我的自定义线程池上执行。
从概念上讲,类似于:
class Example
{
async ValueTask DoStuff(int something)
{
// .. do some stuff in here, might complete synchronously or not, who knows ..
}
private void Test()
{
for (int i = 0; i < 1_000; i++)
{
Func<ValueTask> method = () => DoStuff(1);
MyThreadPool.Queue(method);
}
}
}
最好的方法是什么?
我目前的做法是这样的:
class Example
{
async ValueTask DoStuff(int something)
{
// .. do some stuff in here, might complete synchronously or not, who knows ..
}
private void Test()
{
SynchronizationContext myContext = new MyCustomThreadPoolSynchronisationContext();
TaskScheduler myScheduler;
var prevCtx = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(myContext);
myScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
finally
{
SynchronizationContext.SetSynchronizationContext(prevCtx);
}
var myTaskFactory = new TaskFactory(myScheduler);
for (int i = 0; i < 1_000; i++)
{
myTaskFactory.StartNew(() => DoStuff(i).AsTask());
}
}
}
这似乎可行,但必须将 ValueTask 转换为 Task 并将其提交给 TaskFactory 感觉异常笨重。
并且必须安装我的同步上下文,只是为了能够推迟适当的TaskScheduler(然后立即退回到旧的同步上下文)感觉也很糟糕。
我目前的方法是否存在概念上的缺陷?
更好的是,有没有更好、不那么尴尬的方法?
【问题讨论】:
-
与一堆我不在乎谁执行它们任务相比,我无法理解自定义线程池的真棒......所以...... 为什么?
-
因此,您使用了一大堆方法,这些方法基本上被声明为“我通常可以在没有线程切换或分配的情况下同步完成”,并且您将它们强制到另一个线程上。为什么?
-
为什么不使用限制在共享线程池的 x 个线程上运行的 TaskScheduler?而不是自定义线程池。
-
自定义线程池是我听过的最糟糕的想法之一。
-
感谢@TheodorZoulias,非常有趣的方法。在一个理想的世界中,我仍然更喜欢定制的线程池,但是通过工作窃取队列来有效地实现它是一件痛苦的事情。这可能是一个很好的权衡!我预计峰值时每秒最多有几千个(价值)任务。该应用程序的其余部分由于其工作性质而对 GC 非常重,总是很高兴在可能/明智的情况下减少一点压力 - 虽然没有破坏性。只是觉得奇怪,似乎没有任何好的方法(我能想到)与 ValueTasks 相关
标签: c# asynchronous async-await taskscheduler valuetask