I'm having a hard time understanding async and the corresponding behavior. This is a model of the program I'm trying to write, and a repro of the problem I'm having:
namespace AsyncTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting....");
MyClass myClass = new MyClass();
myClass.DoSomeWork();
Console.WriteLine("ending....");
Console.ReadLine();
}
}
class MyClass
{
public bool DoSomeWork()
{
return GetTrue().Result;
}
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
}
}
When I make the GetTrue().Result call, it never returns. My Task<bool> GetTrue() method is a dummy method for repro purposes, but I'm not quite sure why it never comes back. But it returns if I have this:
namespace AsyncTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting....");
MyClass myClass = new MyClass();
myClass.DoSomeWork();
Console.WriteLine("ending....");
Console.ReadLine();
}
}
class MyClass
{
public async void DoSomeWork()
{
await GetTrue();
}
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
}
}
The problem is, with my repro I want the initial behavior. I don't want async void for the calling method. I want to be able to return bool from my calling "normal" method. How can I achieve this? How can I get the first example to run and actually return the bool from DoSomeWork()?
Thank you in advance.
EDIT: Thank you for the answers. I think what the problem is, is that my GetTrue() method isn't a true repro. In my method, I'm not generating the actual Task<bool> object. It's really a call to Task.Factory.FromAsync<bool>() that is creating the Task<bool> object. And it's that task that I don't know how to "start". Any other ideas? Thanks!
You're probably looking for:
Task<bool> GetTrue()
{
return Task.FromResult(true);
}
instead of:
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
In the latter case, you don't even start the task you create. You'd need to start it with Task.Run or Task.RunSynchronously. Usually you don't create tasks directly via new Task(). Check Stephen Toub's "Task.Factory.StartNew" vs "new Task(...).Start" and "Task.Run vs Task.Factory.StartNew".
Depending on what you're trying to achieve, you might be tempted to do this:
Task<bool> GetTrue()
{
return Task.Run(() => true);
}
However, usually this turns to be a known-anti-pattern, check "Should I expose asynchronous wrappers for synchronous methods?".
Updated to address the comments:
... the context is a WCF service. The Task.Factory.FromAsync()
call is wrapping the Begin...() and End...() functions that the
service has pushed to the consumer. But I see no way to actually start
the task and it just hangs.
... it is the client-side making the WCF call. The client-side app is a
Windows Phone 8 application.
You're experiencing a deadlock on the UI thread, because you're blocking on the result of a pending task (with task.Result). The task itself cannot be completed, because the await continuation is posted asynchronously to the dispatcher loop of the UI thread of your WP8 app, which is now blocked. Stephen Cleary explains this in great details in his blog. To avoid this, you should embrace "async all the way down" programming model. It practically means that you should make your UI event and command handlers async as well, and do var result = await task, rather than var result = task.Result in there.
You need to start a task before it does anything.. calling Run will do that for you:
Task<bool> GetTrue()
{
return Task.Run(() => true);
}
This gives the output you expect. Result is a blocking call. If your Task instance never starts.. Result can never return.
Related
In contrast to Task.Wait() or Task.Result, await’ing a Task in C# 5 prevents the thread which executes the wait from lying fallow. Instead, the method using the await keyword needs to be async so that the call of await just makes the method to return a new task which represents the execution of the async method.
But when the await’ed Task completes before the async method has received CPU time again, the await recognizes the Task as finished and thus the async method will return the Task object only at a later time. In some cases this would be later than acceptable because it probably is a common mistake that a developer assumes the await’ing always defers the subsequent statements in his async method.
The mistaken async method’s structure could look like the following:
async Task doSthAsync()
{
var a = await getSthAsync();
// perform a long operation
}
Then sometimes doSthAsync() will return the Task only after a long time.
I know it should rather be written like this:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Run(() =>
{
// perform a long operation
};
}
... or that:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Yield();
// perform a long operation
}
But I do not find the last two patterns pretty and want to prevent the mistake to occur. I am developing a framework which provides getSthAsync and the first structure shall be common. So getSthAsync should return an Awaitable which always yields like the YieldAwaitable returned by Task.Yield() does.
Unfortunately most features provided by the Task Parallel Library like Task.WhenAll(IEnumerable<Task> tasks) only operate on Tasks so the result of getSthAsync should be a Task.
So is it possible to return a Task which always yields?
First of all, the consumer of an async method shouldn't assume it will "yield" as that's nothing to do with it being async. If the consumer needs to make sure there's an offload to another thread they should use Task.Run to enforce that.
Second of all, I don't see how using Task.Run, or Task.Yield is problematic as it's used inside an async method which returns a Task and not a YieldAwaitable.
If you want to create a Task that behaves like YieldAwaitable you can just use Task.Yield inside an async method:
async Task Yield()
{
await Task.Yield();
}
Edit:
As was mentioned in the comments, this has a race condition where it may not always yield. This race condition is inherent with how Task and TaskAwaiter are implemented. To avoid that you can create your own Task and TaskAwaiter:
public class YieldTask : Task
{
public YieldTask() : base(() => {})
{
Start(TaskScheduler.Default);
}
public new TaskAwaiterWrapper GetAwaiter() => new TaskAwaiterWrapper(base.GetAwaiter());
}
public struct TaskAwaiterWrapper : INotifyCompletion
{
private TaskAwaiter _taskAwaiter;
public TaskAwaiterWrapper(TaskAwaiter taskAwaiter)
{
_taskAwaiter = taskAwaiter;
}
public bool IsCompleted => false;
public void OnCompleted(Action continuation) => _taskAwaiter.OnCompleted(continuation);
public void GetResult() => _taskAwaiter.GetResult();
}
This will create a task that always yields because IsCompleted always returns false. It can be used like this:
public static readonly YieldTask YieldTask = new YieldTask();
private static async Task MainAsync()
{
await YieldTask;
// something
}
Note: I highly discourage anyone from actually doing this kind of thing.
Here is a polished version of i3arnon's YieldTask:
public class YieldTask : Task
{
public YieldTask() : base(() => { },
TaskCreationOptions.RunContinuationsAsynchronously)
=> RunSynchronously();
public new YieldAwaitable.YieldAwaiter GetAwaiter()
=> default;
public new YieldAwaitable ConfigureAwait(bool continueOnCapturedContext)
{
if (!continueOnCapturedContext) throw new NotSupportedException();
return default;
}
}
The YieldTask is immediately completed upon creation, but its awaiter says otherwise. The GetAwaiter().IsCompleted always returns false. This mischief makes the await operator to trigger the desirable asynchronous switch, every time it awaits this task. Actually creating multiple YieldTask instances is redundant. A singleton would work just as well.
There is a problem with this approach though. The underlying methods of the Task class are not virtual, and hiding them with the new modifier means that polymorphism doesn't work. If you store a YieldTask instance to a Task variable, you'll get the default task behavior. This is a considerable drawback for my use case, but I can't see any solution around it.
I have a problem where I have a library that uses an async function, GetParametersByPathAsync (which is defined here: https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Services/SimpleSystemsManagement/Generated/_mobile/AmazonSimpleSystemsManagementClient.cs#L2718)
I have a library function defined as
Task<Dictionary<string,string>> GetAllParameters(string region)
{
var pars = DoParameterGatheringWork(reigion);
...(do some more work)
return dict;
}
which calls another method
async Task<Dictionary<string,string>> DoParameterGatheringWork(string region)
{
...
var response = await GetParametersByPathAsync(requestObj);
... (process the response)
return parameterDict;
}
that awaits on the GetParametersByPathAsync and gathers things.
This is a problem because GetAllParameters has to be called by my service from a static constructor and initialize a parameter Dictionary<string,string> MyParameters { get; }
I would like to stop this bubbling up of Tasks at some point in the library, so it can just expose Dictionary<string,string> GetAllParameters(string region), not the Task version. (I am completely fine with it becoming synchronous..)
I don't think I should be just doing Task.Wait() or Task.Result either because that will cause deadlocks.
Maybe this isn't the best way to go about it, but I am unsure how to continue on from here.
Any thoughts would be appreciated!
Edit:
Here is the constructor code I would like to have:
public class MyConfiguration
{
static MyConfiguration()
{
...
Parameters = ServiceConfiguration.GetAllParameters(); // (library call)
}
public static Dictionary<string, string> Parameters { get; }
}
and the client will be able to use this anywhere just by MyConfiguration.Parameters["IAMAPARAMETER"]
After comment: at the end of this answer: How to call the async method from a non-async method
Apparently DoParameterGatheringWork is a function that normally would have to do some busy waiting for another process, like a database, or a file, or some information from the internet.
The designer of that function thought it would be a waste of time if your thread would be waiting idly for the result of this remove action. Therefore he decided to make it async, so the callers could do other things while the other process would process the request.
You saw correct that this means that all callers should also be async, and that a constructor can't be async.
If you want to benefit from the advantages of async-await (meaning that your callers can continue processing instead of idly waiting, make your constructor ligthweight and let some Create function do the async job you normally would do in the constructor. Force everyone who wants an object of your class to use this async Create function.
public class MyConfiguration
{
// Static async Create function, does everything you'd normally do in the constructor:
public static async Task<MyConfiguration> CreateAsync()
{
Dictionary<string,string> allParameters = await ServiceConfiguration.GetAllParameters(...);
MyConfiguration createdConfiguration = new MyConfiguration(allParameters);
return createdConfiguration;
}
// make sure that no one except CreateAsync can call the constructor:
private MyConfiguration(Dictionary<string,string> allParameters)
{
parameters = allParameters;
}
}
What you do is that you make the constructor as lightweight as possible and do all the difficult stuff, including await in the CreateAsync function.
Usage:
The following will lead to compiler error, so you know the problem before you start running:
MyConfiguration config = new MyConfiguration(...);
Proper usage:
async Task<...> DoSomethingAsync(...)
{
...
// I need a configuration:
MyConfiguration config = await MyConfiguration.Create();
// from here you can use the fully initialized MyConfiguration object:
config.DoSomethingElse();
...
}
Simple comme bonjour
Addition: how to call async method from a non-async function
To call an async function from a non-async method, use Task.Run to start the async function, Task.Wait to wait for the async function to complete and Task.Result to get the return value of the async function.
static void Main(string[] args)
{
// call an async function:
var asyncTask = Task.Run( () => MyAsyncFunction(...));
// if desired: do other things
DoSomethingElse();
// now you need the result of the async function
asyncTask.Wait();
var returnValue = asyncTask.Result;
Process(returnvalue);
}
How I can wait for task to complete before repeating it
List<ushort> IdsInProgress = new List<ushort>();
public async Task<string> RunMyTask(ushort Id)
{
if (IdsInProgress.Contains(Id))
{
//Here Wait previous task to finish
//and then re-run it
return await MyTask(Id);
}
return await MyTask(Id);
}
public Task<string> MyTask(ushort Id)
{
IdsInProgress.Add(Id);
String MyString;
//do something
IdsInProgress.Remove(Id);
return Task.FromResult(MyString);
}
After dasblinkenlight comments about thread-safe and sync I ended up with this solution. Not sure if this is the best way.
I remove IdsInProgress because I don't need it anymore.
private readonly object obj = new object();
public Task<string> MyTask(ushort Id)
{
lock(obj)
{
String MyString;
//do something
return Task.FromResult(MyString);
}
}
Now if I run this method 100 times they would run one after the other.
Based on luaan comment it's better to do this like this
private SemaphoreSlim semaphore = new new SemaphoreSlim(1);
public Task<string> MyTask(ushort Id)
{
semaphore.Wait();
String MyString;
//do something
semaphore.Release();
return Task.FromResult(MyString);
}
I would suggest you take a look at the ISynchronizeInvoke interface.
The interface allows methods to be called from any thread and marshals that call to the proper thread.
As the goal is to synchronously executes tasks, the Invoke method can be used to delegate and marshal the call to the thread that created this object.
Using this method ensures that the process or task is finished before returning.
Implementing this method is quite straightforward:
public object Invoke(Delegate method, object[] args)
{
return method.DynamicInvoke(args);
}
Typically you would use this method as followed: invokerObj.Invoke(MyMethod)
Which executes MyMethod on the thread managed by the object (invokerObj) implementing the ISynchronizeInvoke interface.
The property InvokeRequired and the methods BeginInvoke & EndInvokecan be implemented if you also wish the possibility to asynchronously execute a delegate. A nice demonstration can be found over here.
I hope this explains it a bit more.
I have a problem where async methods are being called in the code without await in front of it. Is there a way to find all the awaitable methods that do not have await?
Edit - I'm particularly concerned with the scenario where multiple async methods are being called (ignoring the return values), but only one has await which is enough to make Visual Studio not warn about it.
If you use ReSharper and turn solution-wide analysis on, your methods that are returning tasks that are not being awaited will have the Task portion of the method signature grayed out due to "return value is not used." The caveat here is that this will only find methods that are not being awaited anywhere in your solution; the warning will go away after one or more usages are updated to await (or use/reference the Task).
If you're looking for async methods that don't contain an await call (meaning they don't need to be labeled async), ReSharper will tell you about that too in a similar fashion.
class AClass
{
public async void Foo() //async grayed out
{
DoSomethingAsync();
Console.WriteLine("Done");
}
public Task<bool> DoSomethingAsync() //Task<bool> grayed out
{
return Task.Run(() => true);
}
}
Note this will not work if you have code that looks like this:
class AClass
{
public async void Foo()
{
bool b = DoSomethingAsync().Result;
Console.WriteLine("Done");
}
public Task<bool> DoSomethingAsync()
{
return Task.Run(() => true);
}
}
The async keyword, if present, will still be flagged, which means you can probably figure out pretty quickly a Task is not being awaited, but if the calling method is not marked async you are out of luck.
I tried to use the SwitchTo method today to switch to the GUI thread, and found that the example I lifted it from does not work, simply because the method is not there.
I then found this blurb here:
The reason we got rid of it was because it was so dangerous. The alternative is to bundle up your code inside TaskEx.Run...
My question is simply: Why was it dangerous? What specific dangers would using it lead to?
Note that I did read the rest of that post, so I do understand there are technical limitations here. My question is still, if I'm aware of this, why is it dangerous?
I am considering reimplementing helper methods to give me the specified functionality, but if there is something fundamentally broken, other than that someone decided it was dangerous, I would not do it.
Specifically, very naively, here's how I would consider implementing the required methods:
public static class ContextSwitcher
{
public static ThreadPoolContextSwitcher SwitchToThreadPool()
{
return new ThreadPoolContextSwitcher();
}
public static SynchronizationContextSwitcher SwitchTo(this SynchronizationContext synchronizationContext)
{
return new SynchronizationContextSwitcher(synchronizationContext);
}
}
public class SynchronizationContextSwitcher : INotifyCompletion
{
private readonly SynchronizationContext _SynchronizationContext;
public SynchronizationContextSwitcher(SynchronizationContext synchronizationContext)
{
_SynchronizationContext = synchronizationContext;
}
public SynchronizationContextSwitcher GetAwaiter()
{
return this;
}
public bool IsCompleted
{
get
{
return false;
}
}
public void OnCompleted(Action action)
{
_SynchronizationContext.Post(_ => action(), null);
}
public void GetResult()
{
}
}
public class ThreadPoolContextSwitcher : INotifyCompletion
{
public ThreadPoolContextSwitcher GetAwaiter()
{
return this;
}
public bool IsCompleted
{
get
{
return false;
}
}
public void OnCompleted(Action action)
{
ThreadPool.QueueUserWorkItem(_ => action(), null);
}
public void GetResult()
{
}
}
This would allow me to write code like this:
public async void Test()
{
await ContextSwitcher.SwitchToThreadPool(); // ensure we're not bogging down the UI thread
// do some heavy processing
await _UIContext.SwitchTo(); // presumably saved from the main thread
// update UI with new data
}
Stephen Toub has some more information on the reasoning in this thread.
To summarize, it's not a good idea for two reasons:
It promotes unstructured code. If you have "heavy processing" that you need to do, it should be placed in a Task.Run. Even better, separate your business logic from your UI logic.
Error handling and (some) continuations run in an unknown context. catch/finally blocks in Test would need to handle running in a thread pool or UI context (and if they're running in the thread pool context, they can't use SwitchTo to jump on the UI context). Also, as long as you await the returned Task you should be OK (await will correct the continuation context if necessary), but if you have explicit ContinueWith continuations that use ExecuteSynchronously, then they'll have the same problem as the catch/finally blocks.
In short, the code is cleaner and more predictable without SwitchTo.
ConfigureAwait is actually more dangerous than SwitchTo. Mentally tracking the current context and the last SwitchTo call is no more difficult than tracking where a variable was last assigned. On the other hand, ConfigureAwait switches context if and only if the call actually ran asynchronously. If the task was already completed, the context is preserved. You have no control over this.
It's 2020 and it looks like SwitchTo is set to come back to CLR soon, according to David Fowler and Stephen Toub in this GitHub issue, as there's no more limitations for await inside try/catch.
IMO, using something like await TaskScheduler.Default.SwitchTo() explicitly is better than relying upon ConfigureAwait(false) in the 3rd party library code, especially if we want to make sure that code doesn't execute on any custom synchronization context. I have a blog post with more details on that, including an experimental implementation of SwitchTo.
In a nutshell, I believe the first option from the below clearly indicates the intent, with minimum boilerplate code:
// switch to the thread pool explicitly for the rest of the async method
await TaskScheduler.Default.SwitchTo();
await RunOneWorkflowAsync();
await RunAnotherWorkflowAsync();
// execute RunOneWorkflowAsync on the thread pool
// and stay there for the rest of the async method
await Task.Run(RunOneWorkflowAsync).ConfigureAwait(false);
await RunAnotherWorkflowAsync();
await Task.Run(async () =>
{
// start on the thread pool
await RunOneWorkflowAsync();
await RunAnotherWorkflowAsync();
}).ConfigureAwait(false);
// continue on the thread pool for the rest of the async method
// start on whatever the current synchronization context is
await RunOneWorkflowAsync().ConfigureAwait(false);
// continue on the thread pool for the rest of the async method,
// unless everything inside `RunOneWorkflowAsync` has completed synchronously
await RunAnotherWorkflowAsync();
The SwitchTo extension method is available in the Microsoft.VisualStudio.Threading package. Here is the signature of this method:
public static
Microsoft.VisualStudio.Threading.AwaitExtensions.TaskSchedulerAwaitable
SwitchTo(this System.Threading.Tasks.TaskScheduler scheduler,
bool alwaysYield = false);
And here is an example of how to use it:
using Microsoft.VisualStudio.Threading;
private async void Button_Click(object sender, EventArgs e)
{
var ui = TaskScheduler.FromCurrentSynchronizationContext(); // Capture the UI thread
// Do something on the UI thread
await TaskScheduler.Default.SwitchTo(); // Switch to the ThreadPool
// Do something on the ThreadPool
await ui.SwitchTo(); // Switch back to the UI thread
// Do something on the UI thread
}