Прошу прощения за длинный вопрос. Я экспериментировал с Орлеаном, чтобы узнать о его различных свойствах, и эти вопросы логически находятся под одним зонтом.
Первый тест включал отправку запроса от клиента к определенному зерну каждую 1 секунду, в то время как зерно требовало 10 секунд для выполнения запросов. Код такой:
// 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;
}
Вывод консоли:
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
Поскольку зерна в Орлеане являются однопоточными, вызывается только первый запрос, а остальные запросы ставятся в очередь на стороне зерна. Мои вопросы по этой части: -
В обычном C #, когда вызывается асинхронный метод, он продолжает работу в основном потоке, пока не встретит оператор await, когда он запускает ожидаемое выражение как другую задачу и возвращает эту задачу. Таким образом, вызывающий блокируется до тех пор, пока не сработает оператор ожидания. Точно так же и здесь клиент должен быть заблокирован на 10 секунд, после чего первый запрос на зернистость вернет Задачу. Однако этого не происходит. Клиент продолжает планировать задачи без блокировки.
- Итак, вызов зерна от клиента
FireAndForget
? - Если да, то как им вернуть объект Task?
- Есть ли какая-либо блокировка, когда клиент обращается к объекту зерна, а среда выполнения возвращает объект Task обратно клиенту?
Второй тест включал отправку запроса от зерна к зерну, в котором второе зерно ожидает 10 секунд, прежде чем вернуться. Код такой:
// 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;
}
Вывод консоли:
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
Я вижу здесь нечто похожее на то, что произошло с клиентом в первом эксперименте. Итак, эти вопросы все еще существуют. Однако здесь происходит еще одна странная вещь. Консольный вывод внутреннего зерна нигде не появляется. Почему не выполняется внутренняя зернистость? Если я включаю закомментированную строку в коде внешней зернистости и ожидаю выполнения задачи внутренней зернистости, появляется следующий вывод, который кажется допустимым.
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
Task t = sensor.SubmitTemperatureAsync((float)temperature);
должна бытьawait sensor.SubmitTemperatureAsync((float)temperature);
или позвонитьawait t
куда-нибудь после. - person Tseng   schedule 30.07.2018Thread.Sleep(10000);
блокирует поток,Task.Delay(10000)
- нет. ВдобавокThread.Sleep(1000000000)
это>
, затем00:30
;) - person Tseng   schedule 30.07.2018Thread.Sleep(n)
- _2 _ !!! - person Tseng   schedule 30.07.2018Thread.Sleep(1000000000) is > then 00:30
. Какое значение имеют 30-е годы? - person AvinashK   schedule 31.07.2018