在自定义线程池上运行 ValueTasks

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

我希望在自定义线程池上执行一堆

ValueTask
返回函数 - 即在我自己生成和处理的一堆线程上,而不是默认的
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
(然后立即回到旧的同步上下文)也感觉很不舒服。

我当前的方法是否存在概念上的缺陷?

更好的是,有没有更好、更不尴尬的方法来做到这一点?

c# asynchronous async-await scheduled-tasks valuetask
1个回答
3
投票

我读到的有关创建自定义线程池的所有内容都说不要这样做。

另一种方法是在共享线程池上使用自定义任务调度程序。

您可以像这样使用这个 TaskScheduler 类:

static async Task Main(string[] args)
{
    // Create a scheduler that uses four threads.
    LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(4);
    List<Task> tasks = new List<Task>();

    TaskFactory factory = new TaskFactory(lcts);
    CancellationTokenSource cts = new CancellationTokenSource(10000);

    // Start 20 tasks that will run 4 threads at 100% CPU
    for (var i = 0; i < 20; i++)
        tasks.Add(factory.StartNew(() => {
            while (true)
                if (cts.Token.IsCancellationRequested)
                    break;
        },cts.Token));

    await Task.WhenAll(tasks);
    cts.Dispose();
}
© www.soinside.com 2019 - 2024. All rights reserved.