Orleans single threaded nature not respected by ContinueWith - c#

I have the following code (https://github.com/avinash0161/OrleansExperiments/tree/c0155b4b0c8c1bfe60aea8624f2cc83a52853dc7):
// Client code
Console.WriteLine("Client making a call");
var hashGenerator = client.GetGrain<IGrainA>(0);
hashGenerator.Call_A_ToTemp();
await Task.Delay(1000);
hashGenerator.Call_B_ToTemp();
// GrainA code
public async Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
grain.CallA().ContinueWith((t)=>
{
if(t.IsFaulted)
{
// Silo message timeout is 32s so t.IsFaulted is true
Console.WriteLine("Task Faulted");
Call_A_ToTemp();
}
});
}
public async Task Call_B_ToTemp()
{
Console.WriteLine("Making call B to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
await grain.CallB();
}
// GrainB code
public async Task CallA()
{
Console.WriteLine("Call A came to GrainB");
await Task.Delay(34000); // more than timeout for the caller
}
public Task CallB()
{
Console.WriteLine("Call B came to GrainB");
return Task.CompletedTask;
}
The output for this code is:
Client making a call
Making call A to a fellow grain
Call A came to GrainB
Making call B to a fellow grain
Task Faulted <---------------- This comes after Call_B_ToTemp executes
Making call A to a fellow grain
As we can see, that Call_B_ToTemp executes before Call_A_ToTemp executes completely (ContinueWith part of Call_A_ToTemp is executed later). Is this expected and does it violate the single threaded nature of the grains?
When I replaced the code in Call_A_ToTemp() with:
public async Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
bool isSuccess = false;
while (! isSuccess)
{
try
{
await grain.CallA();
isSuccess = true;
} catch(TimeoutException){
Console.WriteLine("task faulted");
}
}
}
The code now preserves the single threaded nature and Call_B_ToTemp isn't called till all of ContinueWith part of Call_A_ToTemp() is executed. The console output is like:
Client making a call
Making call A to a fellow grain
Call A came to GrainB
Task Faulted
Making call A to a fellow grain
Can anyone please explain this? Is the single threaded nature violated when there is ContinueWith?

The single-threaded nature is not being violated. The compilation warnings in your project makes the source of the issue clear. In particular: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
The method async Task Call_A_ToTemp() never awaits the call to grain B. Instead, it returns immediately after issuing the call. Because the Task returned by Call_A_ToTemp() is immediately completed, another call is allowed to execute on the grain. Once grain.CallA() completes, the continuation (ContinueWith(...)) will execute on the grain's TaskScheduler as soon as possible (eg, while the grain is awaiting another call or sitting idle).
Instead, if the call was awaited or if async was removed from the method and the code changed to return the grain.CallA().ContinueWith(...) call then the expected behavior will be observed. I.e, changing the code to this will give you the expected result:
// removed 'async' here, since we're not awaiting anything.
// using 'async' is preferred, but this is to demonstrate a point about
// using ContinueWith and un-awaited calls
public Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
// Note the 'return' here
return grain.CallA().ContinueWith((t)=>
{
if(t.IsFaulted)
{
// Silo message timeout is 32s so t.IsFaulted is true
Console.WriteLine("Task Faulted");
Call_A_ToTemp();
}
});
}

Related

I have a few questions about asynchronous programming

I use the following code and it works, but I'm not sure if it is the best/recommanded way to do asynchronous programming.
For example, is the following code necessary or can I call UpdateUsername() without writing this code?
NewUsername();
public async void NewUsername()
{
await UpdateUsername();
}
I use "await" twice in my code, is it necessary to use it twice?
Is it always necessary to use "await" before some code that is marked with async, like the "await" before "PlayFabClientAPI.UpdateUserTitleDisplayNameAsync"?
private async Task UpdateUsername()
{
var resultupdatee = await PlayFabClientAPI.UpdateUserTitleDisplayNameAsync(new UpdateUserTitleDisplayNameRequest()
{
DisplayName = "NewName"
});
if (resultupdatee.Error != null)
{
// Handle error if any
Console.WriteLine(resultupdatee.Error.GenerateErrorReport());
}
else
{
Console.WriteLine("User display name updated");
}
}
When gets the line "int Count = 10;" executed? Is it possible that this line gets excuted before "await PlayFabClientAPI.UpdateUserTitleDisplayNameAsync" finished?
I want that "int Count = 10;" is only then executed after the code UpdateUsername() is finished.
NewUsername();
int Count = 10;
Based on that NewUsername returns void, it does not support awaiting, so there is no need to make it an asynchronous method.
public void NewUsername()
{
UpdateUsername();
}
But you need to ensure that int Count = 10 executes after the asynchronous task is done, we cannot let NewUsername return void, otherwise there is nothing to await.
Based on your code I assume that there is no further operation after UpdateUsername, so there is no need for NewUsername to be a async method
public Task NewUsername()
{
return UpdateUsername();
}
But if there is, you need
public async Task NewUsername()
{
await UpdateUsername();
//Operations after UpdateUsername is done.
}
As long as NewUsername returns Task, you can use await to ensure int Count = 10; executes after everything is done.
//Must be in an async function
await NewUsername();
int Count = 10;
As you can see, if there is some operation in a function A that needs to execute after another asynchronous function B is done, then function A needs to be asynchronous. In other words, asynchronous function is transitive. An asynchronous callee makes the caller asynchronous, unless you don't need to ensure the sequence of execution or you block the thread to wait synchronously.
Conclusion, there are 3 ways to do after calling an asynchronous function:
Waiting asynchronously, which is to await it to add operations after the callee is done. This makes the caller asynchronous.
Waiting synchronously, which is to call Wait method on the returned Task value to block the current thread for the completion. This is not recommanded for it makes the asynchronous callings meaningless.
Waiving the returned Task value of the asynchronous callee or the callee returning void, which is not to go ahead executing without waiting for the completion of the callee.

Code after 'await Task.Delay(5000)' is not executing until the execution of relaycommand is completed

In my WPF application, i am calling relaycommand
private void AutoRun(object parameter)
{
for(int i=0;i<10;i++)
{
MoveLotCommand.Execute(0);
}
}
which inturns call another relay command
private void MoveLot(object parameter)
{
//Some Code
var Task = StartLotProcessing(currentAssemblyPlant);
}
}
and this relay command will call another async function
async Task StartLotProcessing(int currentAssemblyPlant)
{
await Task.Delay(5000);
var nextAssemblyPlant = currentAssemblyPlant + 1;
//Process after await
}
The issue is, my code after 'await Task.Delay(5000)' does not executes until my AutoRun() function execution is completed.
I am trying to execute the await async code for each variable in my for loop.
Any help would be appreciated and sorry for my explanation.
You are not calling the method correctly : you are missing the await operator to indicate that you have to wait, otherwise you effectively schedule the task but do not wait for it. The task is scheduled in a synchronous fashion, hence when your method returns.
Change your call to this, and the issue should go away:
await StartLotProcessing(currentAssemblyPlant);
The problem appears to be that you are calling StartLotProcessing asynchronously but not waiting for the task to complete before moving on.
Ideally you would call use async/await the whole way up the stack:
await MoveLotCommand.Execute(0);
...
await StartLotProcessing(currentAssemblyPlant);
If you're unable to do that, then you should call
var task = StartLotProcessing(currentAssemblyPlant);
...
task.Wait();

Does calling await on a no task creation method do anything Asynchronous?

Consider the following:
public async Task<bool> DoSomethingAsync()
{
// no creation of a task in these statements
statement2;
statement3;
statement4;
return Task.FromResult( true );
}
public async Task MyMethod()
{
statement1;
await DoSomethingAsync().ConfigureAwait( false );
statement5;
}
Is there any asynchronous behaviour to be run when awaiting DoSomethingAsync?
Is there any asynchronous behaviour to be run when awaiting DoSomethingAsync?
No, there isn't. When DoSomthingAsync is called, it is executed whole and returned Task is already finished. So when await tries to wire-up the callback logic, it finds out the task is already finished and just continues execution without bothering with the callback logic.
But all of those are implementation details and it is possible those details will change. You should not build your code with the assumption this code will run synchronously. Any addition of await inside DoSomthingAsync will make the code completely asynchronous without you noticing.
Also, DoSomthingAsync the way it is right now does not compile. You either remove the async, in which case it is clear that DoSomthingAsync is not asynchronous. Or you just have return true; , in which case the compiler should warn you that method does not contain any await and will complete synchronously.
Considering your question in comment:
public async Task<bool> DoSomethingAsync()
{
statement2;
await statement3; // << Diverges here
statement4;
return true;
}
// all code below this line is completely irrelevant
// to whenever or where the code above diverges
public async Task MyMethod()
{
statement1;
await DoSomethingAsync().ConfigureAwait( false );
statement5;
}

Task being marked as RanToCompletion at await, when still Running

I'm still getting up to speed with async & multi threading. I'm trying to monitor when the Task I Start is still running (to show in a UI). However it's indicating that it is RanToCompletion earlier than I want, when it hits an await, even when I consider its Status as still Running.
Here is the sample I'm doing. It all seems to be centred around the await's. When it hits an await, it is then marked as RanToCompletion.
I want to keep track of the main Task which starts it all, in a way which indicates to me that it is still running all the way to the end and only RanToCompletion when it is all done, including the repo call and the WhenAll.
How can I change this to get the feedback I want about the tskProdSeeding task status?
My Console application Main method calls this:
Task tskProdSeeding;
tskProdSeeding = Task.Factory.StartNew(SeedingProd, _cts.Token);
Which the runs this:
private async void SeedingProd(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
int totalSeeded = 0;
var codesToSeed = await _myRepository.All().ToListAsync(token);
await Task.WhenAll(Task.Run(async () =>
{
foreach (var code in codesToSeed)
{
if (!token.IsCancellationRequested)
{
try
{
int seedCountByCode = await _myManager.SeedDataFromLive(code);
totalSeeded += seedCountByCode;
}
catch (Exception ex)
{
_logger.InfoFormat(ex.ToString());
}
}
}
}, token));
Thread.Sleep(30000);
}
}
If you use async void the outer task can't tell when the task is finished, you need to use async Task instead.
Second, once you do switch to async Task, Task.Factory.StartNew can't handle functions that return a Task, you need to switch to Task.Run(
tskProdSeeding = Task.Run(() => SeedingProd(_cts.Token), _cts.Token);
Once you do both of those changes you will be able to await or do a .Wait() on tskProdSeeding and it will properly wait till all the work is done before continuing.
Please read "Async/Await - Best Practices in Asynchronous Programming" to learn more about not doing async void.
Please read "StartNew is Dangerous" to learn more about why you should not be using StartNew the way you are using it.
P.S. In SeedingProd you should switch it to use await Task.Delay(30000); insetad of Thread.Sleep(30000);, you will then not tie up a thread while it waits. If you do this you likely could drop the
tskProdSeeding = Task.Run(() => SeedingProd(_cts.Token), _cts.Token);
and just make it
tskProdSeeding = SeedingProd(_cts.Token);
because the function no-longer has a blocking call inside of it.
I'm not convinced that you need a second thread (Task.Run or StartNew) at all. It looks like the bulk of the work is I/O-bound and if you're doing it asynchronously and using Task.Delay instead of Thread.Sleep, then there is no thread consumed by those operations and your UI shouldn't freeze. The first thing anyone new to async needs to understand is that it's not the same thing as multithreading. The latter is all about consuming more threads, the former is all about consuming fewer. Focus on eliminating the blocking and you shouldn't need a second thread.
As others have noted, SeedingProd needs to return a Task, not void, so you can observe its completion. I believe your method can be reduced to this:
private async Task SeedingProd(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
int totalSeeded = 0;
var codesToSeed = await _myRepository.All().ToListAsync(token);
foreach (var code in codesToSeed)
{
if (token.IsCancellationRequested)
return;
try
{
int seedCountByCode = await _myManager.SeedDataFromLive(code);
totalSeeded += seedCountByCode;
}
catch (Exception ex)
{
_logger.InfoFormat(ex.ToString());
}
}
await Task.Dealy(30000);
}
}
Then simply call the method, without awaiting it, and you'll have your task.
Task mainTask = SeedingProd(token);
When you specify async on a method, it compiles into a state machine with a Task, so SeedingProd does not run synchronously, but acts as a Task even if returns void. So when you call Task.Factory.StartNew(SeedingProd) you start a task that kick off another task - that's why the first one finishes immediately before the second one. All you have to do is add the Task return parameter instead of void:
private async Task SeedingProdAsync(CancellationToken ct)
{
...
}
and call it as simply as this:
Task tskProdSeeding = SeedingProdAsync(_cts.Token);

Looking for guidance to understand how asynchronous Programming with Async and Await works

i go through a msdn sample code where a function is called when button is clicked and when routine is called then Await keyword is used and function has async keyword used.
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
int contentLength = await AccessTheWebAsync();
resultsTextBox.Text +=
String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
}
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
void DoIndependentWork()
{
resultsTextBox.Text += "Working . . . . . . .\r\n";
}
When AccessTheWebAsync is called then await keyword is used, what does it mean?
When this function AccessTheWebAsync() will be executing then DoIndependentWork() function is called and i guess here control will be waiting until this function DoIndependentWork() is finished. Am I right?
again there is another statement called
string urlContents = await getStringTask;
why they use here await. if we do not use await here then what would happen?
Please guide me to understand the code that how it is working.
I have an intro blog post here, and the MSDN docs are also extremely good.
You can think of await as "pausing" the method (without blocking the thread) until the awaitable operation completes. When this happens, it returns a task that is not completed to the calling method, so it also has the option to await.
Here's a brief description about async/await methods.
Async Methods:
Caller is not necessarily blocked for the full execution of async
method
Possible return types
void: “fire-and-forget”
Task: allows to await termination of async method
Task<T>: allows to await termination and get result of type T
No ref or out parameter for async methods
Must again contain an await => Otherwise compile warning
await for Tasks
Await termination of a TPL task
Return result of task (if task with
result type)
Must only occur in async methods => Otherwise compile error
An async method is partly synchronous and partly asynchronous
Caller synchronously executes the method until a blocking await
Thereafter, the method rest is asynchronously executed
async & await Mechanism
Efficient
public async Task<int> GetSiteLengthAsync(string url)
{
HttpClient client = new HttpClient(); <= Sync
Task<string> download1 = client.GetStringAsync(url); <= Sync
string site1 = await download1; <= Async (Another thread)
return site1.Length; <= Async (Another thread)
}
Not sure if that simplier for you to understand that in the following way, but this is how it helped myself:
As you can see, the AccessTheWebAsync returns Task<int> but not just int.
If you would have called it without "await", you would just get the Task<int> object as its result. And could do anything further you want (manually) with that task: for instance, to wait until it finishes theTask.Wait(); and obtain the result of int in theTask.Result.
But await does all that instead of you and returns just int: Task<int> => int.
This is it.
from MSDN:
the await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.await does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
So when the compiler encounter
int contentLength = await AccessTheWebAsync();
it waits till the AccessTheWebAsync() task is complted
please take a look at this example C# Async,Await
All await does is blocks the thread until the result of an async operation returns.
Edit: sorry when I said block I should have said suspend, since blocking would prevent execution from continuing!
Edit2: As Alex pointed out - I should have probably said "execution is suspended" rather than the thread. Basically "Stuff happens until await returns but the point is it appears you are writing and executing synchronous code"
Since async operations have the potential to be take a while (e.g. web service calls), they tend to use callbacks to return a result.
If you have to handle callbacks in your code it can get a little messy, especially when waiting on multiple async tasks that are dependant on each other. Async/await and Task simplify the code so that you can write async code literally in the order you would read it.
e.g. example standard async code with callbacks:
public int CallSomeServiceAndReturnItsValue()
{
int result = 0;
WebService.SomeAsyncServiceCall((svcResult) => { result = svcResult.Value; });
return result;
}
and if you have multiple calls that need to be chained:
public int CallSomeServiceAndReturnItsValue()
{
int result = 0;
WebService.GetSomeIdentifier((svcResult) =>
{
var identifier = svcResult.Value;
WebService.GetResult(identifier, (anotherResult) =>
{
result = anotherResult.Value;
}
}
);
return result;
}
As you can see, it starts getting messy, the code doesn't really read in an order that feels natural. The alternative is to use callback methods instead of anonymous methods but still, the callback methods are far away from the code that called them and things can feel disjointed
The other alternative is of course async/await which is much clearer
public int CallSomeServiceAndReturnItsValue()
{
int identifier = await WebService.GetSomeIdentifier();
return await WebService.GetResult(identifier);
}

Categories