deleyd
asked on
Can a Task.Run().Wait() task end up being "inlined"?
Is it possible for the following task to be "inlined" and run on the current thread when the t.Wait(); is encountered?
(I've tried setting ThreadPool.SetMaxThreads(8 , 8); (This succeeds. My computer has 8 CPUs.) and then launching a dozen tasks via Task.Run() to try and fill up the ThreadPool so my Task t = Task.Run() gets queued but not run. However, I have not been able to get t.Wait(); to "inline to inline the task. So far it just always waits I assume for a free ThreadPool thread to become available.)
Task t = Task.Run(() => MyMethod());
t.Wait();
If so, can you provide some example code that does this?(I've tried setting ThreadPool.SetMaxThreads(8
Short answer is no.
You cannot inline the wait call in that fashion since the Wait method returns a bool and the Run method returns a Task.
If you need to wait for all of your tasks to finish before returning the results, then you should add your tasks to a list and use Task.WaitAll; e.g. -
You cannot inline the wait call in that fashion since the Wait method returns a bool and the Run method returns a Task.
If you need to wait for all of your tasks to finish before returning the results, then you should add your tasks to a list and use Task.WaitAll; e.g. -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace EE_Q29170256
{
class Program
{
static void Main(string[] args)
{
var tasks = new List<Task<int>>(from i in Enumerable.Range(0, 5) select Task.Run(() =>
{
Task.Delay(1000);
return i;
}));
Task.WaitAll(tasks.ToArray());
foreach(var task in tasks)
{
Console.WriteLine($"Task {task.Id} resulted in {task.Result}");
}
Console.ReadLine();
}
}
}
Which produces the following output --saige-
ASKER
My goal is to get the task to be "inlined" by the t.Wait(); statement.
Setting Max Threads to a low value was part of my attempt to accomplish this goal.
The Microsoft documentation for Task.Wait() states:
Wait is a synchronization method that causes the calling thread to wait until the current task has completed. If the current task has not started execution, the Wait method attempts to remove the task from the scheduler and execute it inline on the current thread. If it is unable to do that, or if the current task has already started execution, it blocks the calling thread until the task completes. For more information, see Task.Wait and "Inlining" in the Parallel Programming with .NET blog. https://devblogs.microsoft .com/pfxte am/task-wa it-and-inl ining/
I can accomplish this by doing:
Setting Max Threads to a low value was part of my attempt to accomplish this goal.
The Microsoft documentation for Task.Wait() states:
Wait is a synchronization method that causes the calling thread to wait until the current task has completed. If the current task has not started execution, the Wait method attempts to remove the task from the scheduler and execute it inline on the current thread. If it is unable to do that, or if the current task has already started execution, it blocks the calling thread until the task completes. For more information, see Task.Wait and "Inlining" in the Parallel Programming with .NET blog. https://devblogs.microsoft
I can accomplish this by doing:
Task t = MyMethod();
t.Wait();
I'm trying to determine if inlining can also happen if I first call Task.Run().
ASKER
Here is my current attempt to get a task to inline:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadConsoleApp6
{
class Program
{
static void Main(string[] args)
{
ShowMaxThreads();
ShowAvailableThreads();
bool stat = ThreadPool.SetMaxThreads(8, 8);
ShowAvailableThreads();
var tasks = new List<Task>();
for (int i = 0; i < 8; ++i)
{
tasks.Add(Task.Run(() => Wait5Seconds()));
}
Thread.Sleep(1000);
ShowAvailableThreads();
Thread thread = Thread.CurrentThread;
int threadId = thread.ManagedThreadId;
Console.WriteLine("Main Thread: {0:N0}", threadId);
Console.WriteLine("Main thread is available. Let's run AnotherTask()");
Task t = Task.Run(() => AnotherTask());
t.Wait(); // We're waiting. Why does it not inline task and run it on main thread?
Task.WaitAll(tasks.ToArray());
Console.WriteLine("Press any key");
Console.ReadKey();
}
static private void AnotherTask()
{
Thread thread = Thread.CurrentThread;
int threadId = thread.ManagedThreadId;
Console.WriteLine("Another Task Thread: {0:N0}", threadId);
}
static void Wait5Seconds()
{
Thread.Sleep(5000);
}
static private void ShowMaxThreads()
{
int workerThreads;
int portThreads;
ThreadPool.GetMaxThreads(out workerThreads, out portThreads);
Console.WriteLine("\nMaximum worker threads: \t{0}\nMaximum completion port threads: {1}", workerThreads, portThreads);
}
static private void ShowAvailableThreads()
{
int workerThreads;
int portThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out portThreads);
Console.WriteLine("\nAvailable worker threads: \t{0}\nAvailable completion port threads: {1}\n", workerThreads, portThreads);
}
}
}
I set max threads to 8 because that's the minimum I can for my machine. I then spin off 8 tasks so there are no more available ThreadPool threads. I then try to get AnotherTask() to be inlined, but it insists on waiting instead.
Hi,
There is no warranty to have the inline performed if Task.Run() is invoked as long as it just enqueue the execution of the specified delegate. In the end, what you're trying to obtain?
There is no warranty to have the inline performed if Task.Run() is invoked as long as it just enqueue the execution of the specified delegate. In the end, what you're trying to obtain?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Why are you calling ThreadPool.SetMaxThreads(8