2

タイプの静的フィールドがありますConcurrentQueue

static readonly ConcurrentQueue<int> q = new ConcurrentQueue<int>();

および非同期メソッド:

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;
}

次に、次のコードを実行します。

var nt = NextNum();
q.Enqueue(10);

nt.Wait();
Console.WriteLine("{0}", nt.Result.HasValue ? nt.Result.Value : -1);

そして、出力は10です。

MethodImpl次に、非同期メソッドに属性を追加します。

[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;
}

そして、前述のコードを実行すると、-1.

質問: これは、非同期メソッドでは、返された Task がすぐに開始されないということですか? MethodImplそして、 (with で) 属性を追加すると、AggressiveInliningすぐに開始されますか?

AggressiveInlining で装飾されたメソッドがタスク スケジューラの動作に影響を与えるかどうかを知りたいです。

4

1 に答える 1

2

あなたのテストは非決定論的であるため、タイミング/スレッドスイッチ/マシンの負荷/コア数などの変化に基づいて結果が異なる場合があります.

たとえば、テストを次のように変更した場合:

var nt = NextNum();
Thread.Sleep(1000);
q.Enqueue(10);

-1出力は、なくても可能性が最も高いAggressiveInliningです。

質問: これは、非同期メソッドでは、返された Task がすぐに開始されないということですか? MethodImpl (AggressiveInlining を使用) 属性を追加すると、すぐに開始されますか?

全くない。によって返されるタスクは、NextNum常にすぐに開始されます。ただし、スレッドプールにキューイングされたタスクTask.Runはそうでない場合があります。そこに行動の違いが見られます。

元のテストでは、キューに入れられたタスクは、実行される前に実行されるのにTask.Run十分な時間がかかります。q.Enqueue2 番目のテストでは、 によってキューに入れられたタスクTask.Runがたまたま の前に実行されますq.Enqueue。どちらも非決定論的でありAggressiveInlining、タイミングを変更するだけです。

コメントからの更新:

AggressiveInlining で装飾されたメソッドがタスク スケジューラの動作に影響を与えるかどうかを知りたいです。

いいえ、違います。

于 2013-05-12T12:42:52.593 に答える