Class TaskHolder has a property of type Task. I pass Task as a parameter into constructor and it starts immediately. Is there a way to prevent it from start?
public class Worker
{
public class TaskHolder
{
public TaskHolder(Task objective)
{
Objective = objective;
}
public Task Objective { get; set; }
}
public async Task DoSomething()
{
await Task.Delay(5000);
Debugger.Break(); // Task starts, so debugger stops here!
// Is there a way to prevent it from start?
}
[Test]
public async Task TempTest()
{
// programm starts here:
var t1 = new TaskHolder(DoSomething());
await Task.Delay(10000);
}
}
A Task represents the now-or-future result of an awaitable operation. If that task has already started, that's interesting - but it has nothing to do with the code that is receiving the task.
If you don't want to start something yet, you should probably be passing an Action. You can create a Task from an Action via Task.Run. Or you can simply invoke the action via action() or action.Invoke()`.
If what you want to run is explicitly asynchronous: you can pass Func<Task>. Again, you can start such a delegate with Task.Run if you want a Task that represents the final state. Or you can just invoke it.
(whether to Invoke() it or pass it to Task.Run() depends on whether you want it to use your thread for any of it)
Ultimately, when you called DoSomething(), you started the code running. A timer was scheduled by the Task.Delay, and then the code continued into TaskHolder.
Related
I know this question has been asked for many times on stack overflow but I am looking for some suggestion on my below code. In my application there are many synchronous methods which are hard to modify. I cannot change everything to async await. But I want to run few methods asynchronously.
I have written some code for that. Also I have added the comments that will help to understand my requirement.
Here is my code:
//This class will perform some heavy operation and also going to call an API for tax configuration.
//The original class takes almost 2 sec to respond. Obviously we are refactoring it but also want this class methods to run async way
public static class TaxCalculatorHelper
{
public static Task<double> CalculateTaxAsync(double salary)
{
// I will do some heavy tax calculation here, so I want it to run asynchronously
return Task.FromResult(500.00); // currently returning temporary value
}
}
//The exisiting classes
public class Employee
{
//This method is not going to be async but What I want that Tax calculation which is heavy task that should run asynchronously
public double GetEmployeeFinalSalary(double salary)
{
var taxValue = Task.Run(async () => await TaxCalculatorHelper.CalculateTaxAsync(salary));
//I was doing this
// return taxValue.Result; // I cannot use this because it blocks the calling thread until the asynchronous operation is complete
//Is the below approach correct ?
return taxValue.GetAwaiter().GetResult();
}
}
public class SomeOtherClass
{
private readonly Employee _employee;
public SomeOtherClass()
{
_employee = new Employee();
}
//This will not be async
public void GetEmployeeCtc(double salary)
{
var finalCtc = _employee.GetEmployeeFinalSalary(salary);
}
}
Can anybody review and suggest me the best approach ?
Thank you !!
Assuming this is a UI application, then using Task.Run to push synchronous work off the UI thread is an acceptable approach. It's not a good idea in ASP.NET apps.
For your specific situation, you need to decide what to do about GetEmployeeFinalSalary.
//This method is not going to be async but What I want that Tax calculation which is heavy task that should run asynchronously
...
// return taxValue.Result; // I cannot use this because it blocks the calling thread until the asynchronous operation is complete
You need to decide whether GetEmployeeFinalSalary will be synchronous or asynchronous. If it's synchronous, then it will block the calling thread - that's what synchronous means.
I suspect that you do not want to block the calling thread (I'm assuming that's the UI thread). In that case, GetEmployeeFinalSalary must be asynchronous in order to free up the calling thread:
public async Task<double> GetEmployeeFinalSalaryAsync(double salary)
{
return await Task.Run(async () => await TaxCalculatorHelper.CalculateTaxAsync(salary));
}
I have an async method in my program. I need the task to be asynchronous because it makes network requests, but I don't want it to be reentrant. In other words, if the method is called from code block A, and then again from code block B before the first invocation returns, I want the second invocation to wait until the first invocation finishes before it runs.
If the method were not an async method, I'd be able to accomplish it with this annotation:
[MethodImpl(MethodImplOptions.Synchronized)]
However, the compiler does not allow the annotation to be attached to an async method.
What else can I do?
You can use a SemaphoreSlim, which is a lock with a WaitAsync method on it (and which doesn't mind you releasing it on a different thread to the one you acquired it on).
private readonly SemaphoreSlim methodLock = new SemaphoreSlim(1, 1);
public async Task SomeMethod()
{
await methodLock.WaitAsync();
try
{
...
}
finally
{
methodLock.Release();
}
}
If you're feeling adventurous, you can write an extension method on SemaphoreSlim, letting you do e.g.:
public async Task SomeMethod()
{
using (await methodLock.WaitDisposableAsync())
{
...
}
}
Be careful though: SemaphoreSlim is not recursive (nor can it be). That means if your method is recursive, it will deadlock.
I have gone through several post for converting existing synchronous method to asynchronous. So based on what I have read I am converting the synchronous method to asynchronous like below
Synchronous
public class SomeClass
{
public int DoWork()
{
return DoLongRunningWork();
}
public int DoLongRunningWork()
{
Thread.Sleep(1000);
return 1;
}
}
I converted this to Asynchronous version like below
public class SomeClass
{
public async Task<int> DoWorkAsync()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return await DoLongRunningWorkAsync();
}
public Task<int> DoLongRunningWorkAsync()
{
Thread.Sleep(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return Task.Run(() => 1);
}
}
I am calling this from Main() Method
static void Main()
{
Someclass worker = new SomeClass();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
var result = worker.DoWorkAsync().GetAwaiter().GetResult();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
Console.ReadKey();
}
Is this a correct way to convert synchronous to asynchronous method?
I was expecting Main method's ManagedThreadId will be different than DoWorkAsync and DoLongRunningWorkAsync method's ManagedThreadId. But they are same, why?
I used Thread.Sleep() just to simulate the long running method. As per the suggestions below i should have used Task.Delay() to avoid any confusion.
I dont think i have to put my actual business logic here to understand the concept of async.
As per Stephen Cleary
1> Identify the naturally-asynchronous operations your code is doing.
2>Change the lowest-level API calls to invoke asynchronous APIs (with await) instead of synchronous APIs.
However none of the .Net Libarary methods im using inside LongRunningMethod are naturally-asynchronous or awaitable and also LongRunningMethod is not doing any I/O operation.
Requirement
I have Web API which takes JSON string as input. The JSON needs to be transformed into some C# object. For transformation I am building a C# library which takes JSON string as input and then Transform that JSON string into C# objects based on some rules. The library may take time ( few milliseconds) for Transformation, during this I DO NOT want Web API's main thread to block. The main thread should be free to take any other request while the transformation is going on background thread (some other thread).
public class MyWebApi: ApiController
{
private ILib _myLibrary
public MyWebApi(ILib myLibrary)
{
_myLibrary = myLibrary
}
publi async Task<SomeObject> Transform(string jsonString)
{
// i want to make LongRunningMethod() method awaitable
// or at least it needs to execute on different thread so that
// main thread will be free.
var result = await _myLibrary.LongRunningMethod(jsonString);
return result;
}
}
publi class MyLibrary:ILib
{
// A method that does Transformation
public async Task<SomeObject> LongRunningMethod(string jsonString)
{
var result = new SomeObject();
// parse jsonString here
// and based on some complex rules create SomeObject
// this operation may takes time (lets say few milliseconds)
// i may call some other private methods here or public methods from other library
return result
}
}
based on what I have read I am converting the synchronous method to asynchronous like below
The best way to convert synchronous methods to asynchronous (as I describe in my async brownfield article) is the following:
Identify the naturally-asynchronous operations your code is doing. This is anything that is not running CPU code, e.g., I/O.
Change the lowest-level API calls to invoke asynchronous APIs (with await) instead of synchronous APIs.
Note the compiler warning and change your calling method to be async with a proper (Task/Task<T>) return type. Also add an Async suffix.
Change calling methods to use await, and repeat step (3).
When you run into problems with step (3), check out my articles on async OOP, async MVVM (if applicable), and async brownfield.
Applying these to your code:
Identify the naturally-asynchronous operations your code is doing. This is anything that is not running CPU code, e.g., I/O.
Your lowest-level method has a call to Thread.Sleep, which is not running code. The asynchronous equivalent is Task.Delay.
Change the lowest-level API calls to invoke asynchronous APIs (with await) instead of synchronous APIs.
public int DoLongRunningWork()
{
await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return 1;
}
Note the compiler warning and change your calling method to be async with a proper (Task/Task<T>) return type. Also add an Async suffix.
public async Task<int> DoLongRunningWorkAsync()
{
await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return 1;
}
Change calling methods to use await, and repeat step (3).
public int DoWork()
{
return await DoLongRunningWorkAsync();
}
Note the compiler warning and change your calling method to be async with a proper (Task/Task<T>) return type. Also add an Async suffix.
public async Task<int> DoWorkAsync()
{
return await DoLongRunningWorkAsync();
}
Change calling methods to use await, and repeat step (3).
In this case, since Main cannot be async, you'll need to block with GetAwaiter().GetResult(), just like you currently have.
Final result:
public async Task<int> DoWorkAsync()
{
return await DoLongRunningWorkAsync();
}
public async Task<int> DoLongRunningWorkAsync()
{
await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return 1;
}
I was expecting Main method's ManagedThreadId will be different than DoWorkAsync and DoLongRunningWorkAsync method's ManagedThreadId. But they are same, why?
"Asynchronous" does NOT mean "runs on a different thread." See my async intro for more details about how async/await works.
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.
Lets say at some point at least 10 methods are available at stack as not finished. Many of these methods are dealing with actions that make impact on UI. At this point, I would like to issue a Save command. Save command can finish successfully, or can fail. Based on the result, I would like to make different actions, and only then return execution to those methods that are left on stack.
Now, if I run Save command synchronously, there is no problem. I would like to execute Save command asynchronously, return the execution to message pump (UI), while all the code (methods) on stack should wait for SaveCommand to finish.
Now, as I have understood await, there is no guarantee that a call will be made on same thread (in my case UI thread). SO, I cannot just await the first method that was called (the parent of all other methods in stack), since if a different thread gets started, it will raise a UI exception (accessing UI elements from different thread).
So, how to handle this situation? Example code:
public bool PropertyName {get; set { MethodA(); // some code after };}
public void MethodB() { MethodC(); // some code after }
public void MethodC() { MethodD(); // some code after }
public void MethodD() { MethodE(); // some code after }
// etc
void MEthodK()
{
Save();
}
If you want to (asynchronously) wait for a method, just await the Task returned from that method:
public async Task MethodCAsync() { await MethodDAsync(); // some code after }
public async Task MethodDAsync() { await MethodEAsync(); // some code after }
async Task MethodKAsync()
{
await Save();
}
This will cause a problem with your property setter, which now must be an asynchronous method:
public bool PropertyName { get; private set; }
public async Task SetPropertyNameAsync() { await MethodAAsync(); // some code after }
Unless you call ConfigureAwait(), awaiting a Task from a UI thread will always resume running your code on the UI thread.
You don't have to worry about it.