Resultado da invocação de tarefas em um grão em Orleans

Peço desculpas pela longa pergunta. Tenho experimentado Orleans para conhecer suas várias propriedades e essas questões estão logicamente sob o mesmo guarda-chuva.

O primeiro teste envolveu a solicitação do cliente para um grão específico a cada 1 segundo, enquanto o grão leva 10 segundos para executar os pedidos. O código é este:

// client code
while (1)
{
    Console.WriteLine("Client giving another request");
    double temperature = random.NextDouble() * 40;
    var sensor = client.GetGrain<ITemperatureSensorGrain>(500);
    Task t = sensor.SubmitTemperatureAsync((float)temperature);
    Console.WriteLine(t.Status);
    Thread.Sleep(1000);
 }

// grain code
public Task SubmitTemperatureAsync(float temperature)
{
    long grainId = this.GetPrimaryKeyLong();
    Console.WriteLine($"{grainId} outer received temperature: {temperature}");
    Thread.Sleep(10000);

    Console.WriteLine($"{grainId} outer complete");
    return Task.CompletedTask;
}

A saída do console é:

Client giving another request
Task Status - WaitingForActivation
500 outer received temperature: 32.29987    <------------ print statement inside grain
Client giving another request     <--------------------- client continues
Task Status - WaitingForActivation  <------------------- client isn't blocked
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
500 outer complete

Como os grãos em Orleans são de encadeamento único, apenas a primeira solicitação é invocada e as solicitações de descanso são colocadas em fila no lado da granulação. Minhas perguntas para esta parte são: -

Em C # normal, quando um método assíncrono é chamado, ele continua no thread principal até atingir a instrução de espera quando inicia a expressão aguardada como outra tarefa e retorna essa tarefa. Portanto, o chamador é bloqueado até que a instrução de espera seja atingida. Da mesma forma, também aqui o cliente deve ser bloqueado por 10s, após o qual a primeira solicitação de granulação retorna uma tarefa. No entanto, isso não acontece. O cliente continua agendando tarefas sem ser bloqueado.

Então, é a chamada para grãos do clienteFireAndForget?Se sim, então como eles recuperam o objeto Task?Existe algum tipo de bloqueio envolvido quando o cliente faz uma chamada para um objeto granular e o tempo de execução traz o objeto Task de volta ao cliente?

O segundo teste envolveu a solicitação de um grão para um grão no qual o segundo grão aguarda 10 segundos antes de retornar. O código é este:

// client code
while (1)
{
    Console.WriteLine("Client giving another request");
    double temperature = random.NextDouble() * 40;
    var sensor = client.GetGrain<ITemperatureSensorGrain>(500);
    Task t = sensor.SubmitTemperatureAsync((float)temperature);
    Console.WriteLine("Client Task Status - "+t.Status);

    // make client sleep for a long time after the first request
    // because we don't want any more requests from the client
    Thread.Sleep(1000000000);
}

// outer-grain (ITemperatureSensorGrain) code
public async Task SubmitTemperatureAsync(float temperature)
{
    long grainId = this.GetPrimaryKeyLong();
    Console.WriteLine($"{grainId} outer received temperature: {temperature}");

    while(true)
    {
        Console.WriteLine("Grain sending another request");
        ITempBGrain sensor = this.GrainFactory.GetGrain<ITempBGrain>(400);
        // await sensor.SubmitTempBAsync(temperature);
        Task t = sensor.SubmitTempBAsync(temperature);
        Console.WriteLine("Grain Task Status - "+t.Status);
        Thread.Sleep(1000);
    }
}

// inner-grain (ITempBGrain) code
public Task SubmitTempBAsync(float temperature)
{
    long grainId = this.GetPrimaryKeyLong();
    Console.WriteLine($"{grainId} internal received temperature: {temperature}");
    Thread.Sleep(10000);
    Console.WriteLine($"{grainId} internal complete");
    return Task.CompletedTask;
}

A saída do console é:

Client giving another request
Client Task Status - WaitingForActivation
500 outer received temperature: 10.36764
Grain sending another request       <-------------- Outer grain prints
Grain Task Status - WaitingForActivation 
Grain sending another request  <----------- Inner grain doesn't print
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
warn: Orleans.Runtime.CallbackData[100157]
      Response did not arrive on time in 00:00:30 for message: Request *cli/015ba7a5@d4cdc7ab->S127.0.0.1:30000:0*grn/6424EE47/000001f4 #17: . Target History is: <S127.0.0.1:30000:0:*grn/6424EE47/000001f4:>. About to break its promise.
Grain sending another request
Grain Task Status - WaitingForActivation

O que vejo aqui é algo semelhante ao que aconteceu com o cliente no primeiro experimento. Então, essas perguntas ainda estão lá. No entanto, aqui há mais uma coisa estranha acontecendo. A saída do console do grão interno não aparece em lugar nenhum.Por que o grão interno não está sendo executado? Se eu ativar a linha comentada no código de granulação externa e aguardar a tarefa de granulação interna, a saída a seguir será exibida, que parece válida.

Client giving another request
Client Task Status - WaitingForActivation
500 outer received temperature: 6.332514
Grain sending another request
400 internal received temperature: 6.332514
400 internal complete
Grain sending another request
400 internal received temperature: 6.332514

questionAnswers(1)

yourAnswerToTheQuestion