I have a static field of type ConcurrentQueue
:
static readonly ConcurrentQueue<int> q = new ConcurrentQueue<int>();
and an async method:
static async Task<int?> NextNum()
{
int? n = await Task.Run<int?>(() =>
{
int i = 0;
if (q.TryDequeue(out i)) return i;
return null;
});
return n;
}
Then I execute this code:
var nt = NextNum();
q.Enqueue(10);
nt.Wait();
Console.WriteLine("{0}", nt.Result.HasValue ? nt.Result.Value : -1);
And the output is 10
.
Now I add MethodImpl
attribute to my async method:
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
static async Task<int?> NextNum()
{
int? n = await Task.Run<int?>(() =>
{
int i = 0;
if (q.TryDequeue(out i)) return i;
return null;
});
return n;
}
And when I execute the previously mentioned code I get -1
.
Question: Does this mean in an async method the returned Task does not start immediately? And if we add MethodImpl
(with AggressiveInlining
) attribute it starts immediately?
I want to know if a method decorated with AggressiveInlining has any effect on task scheduler behavior.
Your test is nondeterministic, so the results may be different based on changes in timings / thread switches / load on the machine / number of cores / etc.
E.g., if you change your test to:
var nt = NextNum();
Thread.Sleep(1000);
q.Enqueue(10);
then the output is most likely -1
even without AggressiveInlining
.
Question: Does this mean in an async method the returned Task does not start immediately? And if we add MethodImpl (with AggressiveInlining) attribute it starts immediately?
Not at all. The task returned by NextNum
always starts immediately. However, the task queued to the thread pool by Task.Run
may not. That's where you're seeing the difference in behavior.
In your original test, the task queued by Task.Run
happens to take long enough that q.Enqueue
gets executed before it does. In your second test, the task queued by Task.Run
happens to run before q.Enqueue
. Both are nondeterministic, and AggressiveInlining
just changes the timings.
Update from comments:
I want to know if a method decorated with AggressiveInlining has any effect on task scheduler behavior.
No, it does not.