This is how my code is setup. However I am getting an exception when updating myUIElement in Method2.
"the calling thread cannot access this object because a different
thread owns it.
Should anything after await always be called on UI thread? What am I doing wrong here?
private async void Method1()
{
// I want to wait until Method2 is completed before doing anything else in Method1
await Task.Factory.StartNew(() => Method2());
}
private async void Method2()
{
// Reading few things from configuration etc
await Task.Factory.StartNew(() => SomeAPILoadDataFromSomewhere());
myUIElement.Text = "something useful has happened";
}
}
You shouldn't be using StartNew when you don't actually want the code in question to run in a non-UI thread. Just remove it entirely.
Also note that you should only have async void methods as top level event handlers. Any async method that you intend to await should return a Task.
You should also generally be using Task.Run instead of StartNew where possible.
//This should return a Task and not void if it is used by another asynchronous method
private async void Method1()
{
await Method2();
DoSomethingElse();
}
private async Task Method2()
{
await Task.Run(() => SomeAPILoadDataFromSomewhere());
myUIElement.Text = "something useful has happened";
}
Related
Regarding the right worker method signature I need to understand the following:
is there a point in returning Task instead of void for Worker method (if going sync)?
Should I really wait (call Wait()) on the Worker method (if going sync)?
what should be the return value of Worker method when marked as returning Task object (both if going sync/async)?
what signature and body of Worker method should be, given the work it completes is long-running CPU/IO-bound work? Should I follow this recommendation (if going mixed/async)?
Note
Despite the cpu-bound code, there's a choice to call async versions of io-bound methods (sql queries). So it may be all sync or partially async. As for the nature of code in the Worker method.
public class LoopingService
{
private CancellationTokenSource cts;
// ..
void Worker(CancellationToken cancellationToken)
{
while(!cancellationToken.IsCancellationRequested)
{
// mixed, CPU/IO-bound code
try {
// sql query (can be called either as sync/async)
var lastId = documentService.GetLastDocument().Id;
// get next document from a public resource (third-party code, sync)
// can be moved to a web api
var document = thirdPartyDocumentService.GetNextDocument(lastId);
// apply different processors in parallel
var tasksList = new List<Task>();
foreach(var processor in documentService.Processors) {
// each processor checks if it's applicable
// which may include xml-parsing, additional db calls, regexes
// if it's applicable then document data is inserted into the db
var task = new Task(() => processor.Process(document));
tasksList.Add(task);
task.Start();
}
// or
// var tasksList = documentService.ProcessParallel(document);
Task.WaitAll(tasksList.ToArray(), cancellationToken);
}
catch(Exception ex) {
logger.log(ex);
}
}
}
public void Start()
{
this.cts = new CancellationTokenSource();
Task.Run(() => this.Worker(cts.Token));
}
public void Stop()
{
this.cts.Cancel();
this.cts.Dispose();
}
}
is there a point in returning Task instead of void for Worker method?
If Worker is a truly asynchronous method it should return a Task for you to be able to await it. If it's just a synchronous method runnning on a background thread there is no point of changing the return type from void provided that the method is not supposed to return anything.
what should be the return value of Worker method when marked as returning Task object?
Nothing. Provided that the method is asynchronous and marked as async with a return type of Task, it shouldn't return any value:
async Task Worker(CancellationToken cancellationToken) { ... }
Note that there is no point of defining the method as async unless you actually use the await keyword in it.
what signature and body of Worker method should be given the work it completes is long-running CPU/IO-bound work? Should I follow this recommendation?
Yes, probably. If you for some reason are doing both asynchronous and synchronous (CPU-bound) work in the same method, you should prefer to using an asynchronous signature but not wrap the synchronous stuff in Task.Run. Then your service would look something like this:
public class LoopingService
{
private CancellationTokenSource cts;
async Task Worker(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await ...
}
}
public async Task Start()
{
this.cts = new CancellationTokenSource();
await this.Worker(cts.Token).ConfigureAwait(false);
}
public void Stop()
{
this.cts.Cancel();
this.cts.Dispose();
}
}
Ideally your method should be either asynchronous or CPU-bound but not both though.
If in a library I have this
public async DoSomething()
{
await Foo();
}
I then call this like lib.DoSomething().ConfigureAwait(false).GetAwaiter().GetResult()
Would that give me the same benefit as if the library had originally had
public async DoSomething()
{
await Foo().ConfigureAwait(false);
}
No it will not give you the same benefit. If you have:
public async Task DoSomething()
{
await Foo();
}
And then do
lib.DoSomething().ConfigureAwait(false).GetAwaiter().GetResult()
From, for example, UI thread in WPF application - you will deadlock. Before await Foo() you were on UI thread (there was WPF-specific SynchronizationContext.Current) and after await you will try to return back to UI thread. UI thread is blocked on GetResult() so that will result in deadlock. Actually, ConfigureAwait(false) is useless here.
If on the other hand you have
public async Task DoSomething()
{
await Foo().ConfigureAwait(false);
}
And the do
lib.DoSomething().GetAwaiter().GetResult()
No deadlock will happen, because ConfigureAwait(false) tells specifically to not "continue on captured context", so to not return back to SynchronizationContext (UI thread in this case).
Why does a method returning a Task does not get executed when returning it's instance. I thought this must happen, because awaiting the method/delegate would
put it into some queue and later execute the resulting task.
So why does this Task never gets executed when calling Do()?
public void Do()
{
SomeTask().Wait()
}
public async Task SomeTask()
{
return new Task(() => { Console.WriteLine("Hello World!") });
}
EDIT
Or do I alwas need await Task.Run(...)?
Thank you very much!
You're creating a Task but never starting it, so it's impossible for it to complete.
Use Task.Run to return a "hot" (started) Task instead:
return Task.Run(() => { Console.WriteLine("Hello World!") });
Also, async keyword is unnecessary as you're not awaiting the created task.
I've this method
public void Execute(Action action)
{
try
{
action();
}
finally
{
}
}
and I need to convert it to an async method call like this one
public async Task ExecuteAsync(Action action)
{
try
{
await action();
}
finally
{
}
}
The problem with the code above is that the compiler issue the following error
The 'await' operator can only be used within an async lambda
expression. Consider marking this lambda expression with the 'async'
modifier.
If you want to await on a delegate, it has to be of type Func<Task> or Func<Task<T>>. An Action is equivalent into a void Action() named method. You can't await on void, yet you can await Task Func() or Task<T> Func:
public async Task ExecuteAsync(Func<Task> func)
{
try
{
await func();
}
finally
{
}
}
If this can't be done, it means that internally the method isn't truly asynchronous, and what you actually want to do is execute the synchronous delegate on a thread-pool thread, which is a different matter, and isn't really executing something asynchronously. In that case, wrapping the call with Task.Run will suffice.
Try this:
public async void ExecuteAsync(Action action)
{
await Task.Run(action);
}
Using Task.Run()creates an awaitable by running your action on a different task.
And also bear in mind that handling exceptions on "awaitables" does not work as intended.
Better wrap that action() call in a try catch an do Task.Run() on that wrapper.
Let's simplify your starting point down to:
public void Execute(Action action)
{
action();
}
Because you say the finally isn't important.
Valid but pointless:
public async Task ExecuteAsync(Action action)
{
action();
}
This will be pretty much the same as doing:
public Task ExecuteAsync(Action action)
{
action();
return Task.FromResult(0);
}
That is, it'll do what the non-async was doing, and then return a "completed" Task so nothing is gained. It's worth noting though as it's often a valid part-way-point in moving from non-async to async.
Better:
public async Task ExecuteAsync(Action action)
{
await Task.Run(() => action());
}
Which in this case, because it's a single void-returning call can be simplified to:
public async Task ExecuteAsync(Action action)
{
await Task.Run(action);
}
Whether this is worth doing or not is another matter. This releases the current thread from being used, but transfers to another thread to do the work. If we're just going to await the result of this when it's called then we might as well just call the non-async version and be done with it. If however we're doing WaitAll in the caller, or something else that hence benefits from this, then it could indeed be useful.
Potentially much better though is:
public async Task ExecuteAsync(Action action)
{
await actionAsync();
}
Here there's an Async version of the method we are calling, so we change to make use of that. Now, that could be just the same as the above if actionAsync just spins up a thread or uses the thread pool. If however actionAsync does something using asynchronous I/O then there's a much bigger benefit to this.
Note that in this case we could have just tail-called the Task we get:
public Task ExecuteAsync(Action action)
{
return actionAsync();
}
However, that wouldn't be the same if we needed something done after an await within our method. E.g.:
public void Execute(Action action)
{
action();
otherAction();
}
Would have to become:
public async Task Exectute(Action action)
{
await actionAsync();
await otherActionAsync();
}
Or if otherAction had no async version:
public async Task Exectute(Action action)
{
await actionAsync();
otherAction();
}
Not return value optimization in the traditional sense, but I was wondering when you have a situation like this:
private async Task Method1()
{
await Method2();
}
private async Task Method2()
{
await Method3();
}
private async Task Method3()
{
//do something async
}
This could obviously be written more optimally:
private Task Method1()
{
return Method2();
}
private Task Method2()
{
return Method3();
}
private async Task Method3()
{
//do something async
}
I just wondered whether anyone knew if the (MS) compiler was clever enough not to generate state machines for Method1() and Method2() in the first instance?
No, the C# compiler doesn't optimize it and it should not. These are conceptually two different things, here is a similar question.
IMO, the major difference is in how exceptions are getting propogated into the caller of Method1 and Method2. I demo'ed this behavoir here.
In the first case (without the state machine), an exception will be immediately thrown on the caller's stack frame. If it is unhanded, the app may crash right away (unless there is another async method in the chain of calls on the same stack frame).
In the second case (with the state machine), an exception will remain dormant in the Task object returned to the caller, until it is observed via await task or task.Wait(), some time later. It may get observed on a completely different stack frame, or may not get observed at all. I posted some more details about this here.
Why do you ask a question you can answer in a minute by simply testing it?
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
Console.ReadLine();
}
static async Task MainAsync()
{
await Method1();
}
static async Task Method1()
{
await Method2();
}
static async Task Method2()
{
await Method3();
}
static async Task Method3()
{
Console.Write("Start");
await Task.Delay(1000);
Console.Write("End");
}
}
This creates four different state machines in IL.
The IL code has to be this way, since you can call the methods from anywhere and they have to behave consistently, so any optimization would have to be done on the JIT level, not the C# compiler. If you don't need await, don't use it - that's your responsibility.
A great example would be method overloads:
static Task Method()
{
return Method("Default");
}
static async Task Method(string someString)
{
await SomeThingAsync(someString);
}
It's still just as asynchronous as if you did another await in the parameter-less method - but it avoids a useless state machine.
The only purpose of the async keyword is to allow you to use the await keyword inside a given method. You can still await a method that isn't async - the requirement is returning Task, not having the async keyword.
Using the same example as before, the awaits are superfluous. A simpler way would be this:
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
Console.ReadLine();
}
static async Task MainAsync()
{
await Method1();
await Method2();
}
static Task Method1()
{
return Method2();
}
static Task Method2()
{
return Method3();
}
static async Task Method3()
{
Console.Write("Start");
await Task.Delay(1000);
Console.Write("End");
}
}