I'm working on a multi-tasking network project and I'm new on Threading.Tasks. I implemented a simple Task.Factory.StartNew() and I wonder how can I do it with Task.Run()?
Here is the basic code:
Task.Factory.StartNew(new Action<object>(
(x) =>
{
// Do something with 'x'
}), rawData);
I looked into System.Threading.Tasks.Task in Object Browser and I couldn't find a Action<T> like parameter. There is only Action that takes void parameter and no type.
There are only 2 things similiar: static Task Run(Action action) and static Task Run(Func<Task> function) but can't post parameter(s) with both.
Yes, I know I can create a simple extension method for it but my main question is can we write it on single line with Task.Run()?
private void RunAsync()
{
//Beware of closures. String is immutable.
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
//Do stuff
}
Edit
Due to popular demand I must note that the Task launched will run in parallel with the calling thread. Assuming the default TaskScheduler this will use the .NET ThreadPool. Anyways, this means you need to account for whatever parameter(s) being passed to the Task as potentially being accessed by multiple threads at once, making them shared state. This includes accessing them on the calling thread.
In my above code that case is made entirely moot. Strings are immutable. That's why I used them as an example. But say you're not using a String...
One solution is to use async and await. This, by default, will capture the SynchronizationContext of the calling thread and will create a continuation for the rest of the method after the call to await and attach it to the created Task. If this method is running on the WinForms GUI thread it will be of type WindowsFormsSynchronizationContext.
The continuation will run after being posted back to the captured SynchronizationContext - again only by default. So you'll be back on the thread you started with after the await call. You can change this in a variety of ways, notably using ConfigureAwait. In short, the rest of that method will not continue until after the Task has completed on another thread. But the calling thread will continue to run in parallel, just not the rest of the method.
This waiting to complete running the rest of the method may or may not be desirable. If nothing in that method later accesses the parameters passed to the Task you may not want to use await at all.
Or maybe you use those parameters much later on in the method. No reason to await immediately as you could continue safely doing work. Remember, you can store the Task returned in a variable and await on it later - even in the same method. For instance, once you need to access the passed parameters safely after doing a bunch some other work. Again, you do not need to await on the Task right when you run it.
Anyways, a simple way to make this thread-safe with respect to the parameters passed to Task.Run is to do this:
You must first decorate RunAsync with async:
private async void RunAsync()
Important Notes
Preferably the method marked async should not return void, as the linked documentation mentions. The common exception to this is event handlers such as button clicks and such. They must return void. Otherwise I always try to return a Task or Task<TResult> when using async. It's good practice for a quite a few reasons.
Now you can await running the Task like below. You cannot use await without async.
await Task.Run(() => MethodWithParameter(param));
//Code here and below in the same method will not run until AFTER the above task has completed in one fashion or another
So, in general, if you await the task you can avoid treating passed in parameters as a potentially shared resource with all the pitfalls of modifying something from multiple threads at once. Also, beware of closures. I won't cover those in depth but the linked article does a great job of it.
Regarding Run and StartNew the code below I find most important to know, really. There are legitimate reasons to use either, neither is obsolete or "better" than the other. Be aware simply replacing one with the other is a very bad idea unless you understand this:
//These are exactly the same
Task.Run(x);
Task.Factory.StartNew(x, CancellationToken.None,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
//These are also exactly the same
Task.Factory.StartNew(x);
Task.Factory.StartNew(x, CancellationToken.None,
TaskCreationOptions.None, TaskScheduler.Current);
Side Notes
A bit off topic, but be careful using any type of "blocking" on the WinForms GUI thread due to it being marked with [STAThread]. Using await won't block at all, but I do sometimes see it used in conjunction with some sort of blocking.
"Block" is in quotes because you technically cannot block the WinForms GUI thread. Yes, if you use lock on the WinForms GUI thread it will still pump messages, despite you thinking it's "blocked". It's not.
This can cause bizarre issues in very rare cases. One of the reasons you never want to use a lock when painting, for example. But that's a fringe and complex case; however I've seen it cause crazy issues. So I noted it for completeness sake.
Use variable capture to "pass in" parameters.
var x = rawData;
Task.Run(() =>
{
// Do something with 'x'
});
You also could use rawData directly but you must be careful, if you change the value of rawData outside of a task (for example a iterator in a for loop) it will also change the value inside of the task.
From now you can also :
Action<int> action = (o) => Thread.Sleep(o);
int param = 10;
await new TaskFactory().StartNew(action, param)
I know this is an old thread, but I wanted to share a solution I ended up having to use since the accepted post still has an issue.
The Issue:
As pointed out by Alexandre Severino, if param (in the function below) changes shortly after the function call, you might get some unexpected behavior in MethodWithParameter.
Task.Run(() => MethodWithParameter(param));
My Solution:
To account for this, I ended up writing something more like the following line of code:
(new Func<T, Task>(async (p) => await Task.Run(() => MethodWithParam(p)))).Invoke(param);
This allowed me to safely use the parameter asynchronously despite the fact that the parameter changed very quickly after starting the task (which caused issues with the posted solution).
Using this approach, param (value type) gets its value passed in, so even if the async method runs after param changes, p will have whatever value param had when this line of code ran.
Just use Task.Run
var task = Task.Run(() =>
{
//this will already share scope with rawData, no need to use a placeholder
});
Or, if you would like to use it in a method and await the task later
public Task<T> SomethingAsync<T>()
{
var task = Task.Run(() =>
{
//presumably do something which takes a few ms here
//this will share scope with any passed parameters in the method
return default(T);
});
return task;
}
It's unclear if the original problem was the same problem I had: wanting to max CPU threads on computation inside a loop while preserving the iterator's value and keeping inline to avoid passing a ton of variables to a worker function.
for (int i = 0; i < 300; i++)
{
Task.Run(() => {
var x = ComputeStuff(datavector, i); // value of i was incorrect
var y = ComputeMoreStuff(x);
// ...
});
}
I got this to work by changing the outer iterator and localizing its value with a gate.
for (int ii = 0; ii < 300; ii++)
{
System.Threading.CountdownEvent handoff = new System.Threading.CountdownEvent(1);
Task.Run(() => {
int i = ii;
handoff.Signal();
var x = ComputeStuff(datavector, i);
var y = ComputeMoreStuff(x);
// ...
});
handoff.Wait();
}
Idea is to avoid using a Signal like above.
Pumping int values into a struct prevents those values from changing (in the struct).
I had the following Problem: loop var i would change before DoSomething(i) was called (i was incremented at end of loop before ()=> DoSomething(i,ii) was called). With the structs it doesn't happen anymore. Nasty bug to find: DoSomething(i, ii) looks great, but never sure if it gets called each time with a different value for i (or just a 100 times with i=100), hence -> struct
struct Job { public int P1; public int P2; }
…
for (int i = 0; i < 100; i++) {
var job = new Job { P1 = i, P2 = i * i}; // structs immutable...
Task.Run(() => DoSomething(job));
}
There is another way of doing this. I found it useful.
int param;
ThreadPool.QueueUserWorkItem(someMethod, param);
void someMethod(object parameter){
var param = (int) parameter;
// do the job
}
Related
I've read some threads regards the difference between await and ContinueWith. But no one has answer me completely.
I've got a DataAccess Layer that insert records in a database using Dapper.
The InsertAsync method is:
public Task<int> InsertAsync(TEntity entity)
{
return Connection.InsertAsync(entity, Transaction).ContinueWith(r => Convert.ToInt32(r.Result));
}
I don't use async and await because in my head who will use this method will waiting for the result.
Is correct?
I don't use async and await because in my head who will use this method will waiting for the result. Is correct?
That is not correct. While the await keyword does indeed wait for Connection.InsertAsync to complete before it calls Convert.ToInt32, the moment it starts waiting for Connection.InsertAsync it releases control back to its caller.
In other words, the caller will not be stuck waiting for Connection.InsertAsync to finish. The caller will be told "this will take a while, feel free to do something else", so it can continue.
Now, if the caller themselves was explicitly told to await the InsertAsync(TEntity) method on the same line that you call the method, then it will wait and it won't do anything else (except release control back to its caller), but that's because it was explicitly instructed to wait at that point.
To explain in code:
// I will wait for this result
var myInt = await Connection.InsertAsync(myEntity);
// I will not do this until I receive myInt
var sum = 1 + 1;
var anotherSum = 2 + 2;
var andAnotherSum = 3 + 3;
Without the await, the caller will just move on to the next command and do its work, all the way up to the point where it is finally told that it must await the task returned from InsertAsync(TEntity).
To explain in code:
// I will ask for this result but not wait for it
var myIntTask = Connection.InsertAsync(myEntity);
// I will keep myself busy doing this work
var sum = 1 + 1;
var anotherSum = 2 + 2;
var andAnotherSum = 3 + 3;
// My work is done. I hope the task is already done too.
// If not, I will have to wait for it because I can't put it off any longer.
var myInt = await myIntTask;
I've read some threads regards the difference between await and ContinueWith.
Functionally speaking, there is no difference between the two. However, the ContinueWith syntax has recently fallen out of popular favor, and the await syntax is much more favored because it reduces nesting and improves readability.
In terms of waiting, the behavior is exactly the same.
Personally, I suspect that ContinueWith is a leftover artifact from initially trying to design async methods the same way that promises in JS work, but this is just a suspicion.
That should be fine. However, there is a recommendation to always pass a taskscheduler to Continue with, to avoid any ambiguity of what context the continuation will run in, even if it does not matter in this particular case.
I would prefer the version
public async Task<int> InsertAsync(TEntity entity)
{
var r = await Connection.InsertAsync(entity, Transaction);
return Convert.ToInt32(r);
}
I consider this easier to read, and it will always execute the continuation on the same context as the caller. Behind the scenes it will produce very similar code to your example.
You should definitely prefer async/await over the ContinueWith method.
public async Task<int> InsertAsync(TEntity entity)
{
var result = await Connection.InsertAsync(entity, Transaction);
return Convert.ToInt32(result);
}
The primitive ContinueWith method has many hidden gotchas. Exceptions thrown synchronously, exceptions wrapped in AggregateExceptions, TaskScheduler.Current ambiguity, SynchronizationContext not captured, nested Task<Task>s not properly unwrapped, will all come and bite you at one point or another, if you get in the habit of following the ContinueWith route.
I have a large scale C# solution with 40-ish modules.
I'm trying to convert a service used solution-wide from synchronous to asynchronous.
the problem is I can't find a way to do so without changing the signature of the method.
I've tried wrapping said asynchronous desired operation with Task but that requires changing the method signature.
I've tried changing the caller to block itself while the method is operating but that screwed my system pretty good because it's a very long calling-chain and changing each of the members in the chain to block itself is a serious issue.
public SomeClass Foo()
{
// Synchronous Code
}
Turn this into:
public SomeClass Foo()
{
//Asynchronous code
}
whilst all callers stay the same
public void DifferentModule()
{
var class = Foo();
}
Any implementation that fundamentally changes something from sync to async is going to involve a signature change. Any other approach is simply not going to work well. Fundamentally: async and sync demand different APIs, which means: different signatures. This is unavoidable, and frankly "How to convert synchronous method to asynchronous without changing it's signature?" is an unsolvable problem (and more probably: the wrong question). I'm sorry if it seems like I'm not answering the question there, but... sometimes the answer is "you can't, and anyone who says you can is tempting you down a very bad path".
In the async/Task<T> sense, the most common way to do this without breaking compatibility is to add a new / separate method, so you have
SomeReturnType Foo();
and
Task<SomeReturnType> FooAsync(); // or ValueTask<T> if often actually synchoronous
nothing that Foo and FooAsync here probably have similar but different implementations - one designed to exploit async, one that works purely synchronously. It is not a good idea to spoof one by calling the other - both "sync over async" (the synchronous version calling the async version) and "async over sync" (the async version calling the sync version) are anti-patterns, and should be avoided (the first is much more harmful than the second).
If you really don't want to do this, you could also do things like adding a FooCompleted callback event (or similar), but : this is still fundamentally a signature change, and the caller will still have to use the API differently. By the time you've done that - you might as well have made it easy for the consumer by adding the Task<T> API instead.
The common pattern is to add an Async to the method name and wrap the return type in a Task. So:
public SomeClass Foo()
{
// Synchronous Code
}
becomes:
public Task<SomeClass> FooAsync()
{
// Asynchronous Code
}
You'll end up with two versions of the method, but it will allow you to gradually migrate your code over to the async approach, and it won't break the existing code whilst you're doing the migration.
If you desperately need to do this, it can be achieved by wrapping the Synchronous code that needs to become Asynchronous in a Task this can be done like this:
public SomeClass Foo()
{
Task t = Task.Run(() =>
{
// Do stuff, code in here will run asynchronously
}
t.Wait();
// or if you need a return value: var result = t.Wait();
return someClass;
// or return result
}
Code you write inside the Task.Run(() => ...) will run asynchronously
Short explanation: with Task t = Task.Run(() => ...) we start a new Task, the "weird" parameter is a Lambda expression, basically we're passing a anonymous Method into the Run method which will get executed by the Task
We then wait for the task to finish with t.Wait();. The Wait method can return a value, you can return a value from an anonymous method just like from any method, with the return keyword
Note: This can, but should not be done. See Sean's answer for more
What's difference between this two asynchronous methods? If didn't, In which situation this two kind of methods can was different?
Thanks.
public async Task<int> MyMethod1Async()
{
return 1;
}
public async Task<int> MyMethod2Async()
{
return await new Task<int>(() => 1);
}
Taking a look at the two methods:
public async Task<int> MyMethod1Async()
{
return 1;
}
This will run synchronously because there are no "await" operators in it - it just returns 1, so it's no different than if you had just done the following:
public int MyMethod1()
{
return 1;
}
The following method is probably a better illustration of the difference between different "types" of async:
public async Task<string> MyMethod1Async()
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("SomeBaseAddress");
// This will return control to the method's caller until this gets a result from the server
HttpResponseMessage message = await client.GetAsync("SomeURI");
// The same as above - returns control to the method's caller until this is done
string content = await message.Content.ReadAsStringAsync();
return content;
}
}
Code like this won't necessarily spawn extra threads (unless that's how Microsoft happened to have implemented those particular library calls). Either way, await/async does not require the creation of additional threads; it can run asynchronously on the same thread.
My standard illustration of this fact is as follows: suppose you go a restaurant with 10 people. When the waiter comes by, the first person he asks for his order isn't ready; however, the other 9 people are. Thus, the waiter asks the other 9 people for their orders and then comes back to the original guy hoping he'll be ready to order by then. (It's definitely not the case that they'll get a second waiter to wait for the original guy to be ready to order and doing so probably wouldn't save much time anyway). That's how async/await works in many cases (the exception being that some of the Task Parallel library calls, like Thread.Run(...), actually are executing on other threads - in our illustration, bringing in a second waiter - so make sure you check the documentation for which is which).
The next item you list won't work because you just create the task, you don't actually do anything with it:
public async Task<int> MyMethod2Async()
{
return await new Task<int>(() => 1);
}
I'm assuming that you actually intended to do something like the following:
public async Task<int> MyMethod2Async()
{
return await Task.Run<int>(() => 1);
}
This will run the lambda expression in the thread pool, return control to MyMethod2Async's caller until the lambda expression has a result, and then return the value from the lambda expression once it does have a result.
To summarize, the difference is whether you're running asynchronously on the same thread (equivalent to the first guy at your table telling the waiter to come back to him after everyone else has ordered) or if you're running the task on a separate thread.
At risk of oversimplifying things a lot, CPU-bound tasks should generally be run asynchronously on a background thread. However, IO-bound tasks (or other cases where the holdup is mostly just waiting for some kind of result from an external system) can often be run asynchronously on the same thread; there won't necessarily be much of a performance improvement from putting it on a background thread vs. doing it asynchronously on the same thread.
The first method returns an already completed task with a Result of 1.
The second method returns a Task<int> that will never complete.
What I don't understand is the following snippet from MSDN:
Note that the method is now marked with the new async keyword; this is
simply an indicator to the compiler that lets it know that in the
context of this method, the keyword await is to be treated as a point
where the workflow returns control to its caller and picks up again
when the associated task is finished.
How is that any different than how non-async methods work?
If I do
int x;
x = SomeNormalFunctionThatReturnsAnInt();
Console.WriteLine(x);
or
int x;
Task<int> task = SomeAsyncFunctionThatReturnsAnInt();
x = await task;
Console.WriteLine(x);
then from the perspective of the caller, the order of execution is the exact same: an int named x is defined, a function that returns an int is run, and when that funcion is done running, its return value is set to x, which is then written to the console.
from the perspective of the caller, the order of execution is the exact same
Yes and no.
If you await all tasks as soon as they are returned to you, then yes, that method in isolation is seeing the same "order of execution". This is actually the entire point of async/await - it allows writing most asynchronous code in a way that is very natural and similar to equivalent synchronous code.
However, the caller must be aware that it has to be asynchronous. That is, the caller generally uses await, which means that it must be async. There are some added twists that come in with asynchronous code. One example: if this is executed on a UI thread, then synchronous code knows that nothing else can execute on the UI thread between SomeNormalFunctionThatReturnsAnInt and Console.WriteLine; however, asynchronous code uses await, so it must accept that anything else can execute on the UI thread between SomeAsyncFunctionThatReturnsAnInt and Console.WriteLine. So, looking at it from that context, it's not the exact same; asynchronous methods may have their "order of execution" paused while other code runs.
If you weren't waiting the result of the function x could be not initialized. But here you wait for it so there is no difference.
you need to have some read on the async and sync to see what happens in performance level ,
in your example the result is not different as you are saying the method to wait in line of await but lets have a look at the following code snippet
class Program {
private static string result;
static void Main() {
SaySomething();
Console.WriteLine(result);
}
static async Task<string> SaySomething() {
await Task.Delay(5);
result = "Hello world!";
return “Something”;
}
}
can you try to calculate the output, the result is nothing, why ?
with the await we let the main task continue as we wait 5 milliseconds before returning result, have a look at
https://msdn.microsoft.com/en-gb/library/mt674882.aspx
I saw this example at the end of Stephen's book.
This code can be accessed by more than one thread.
static int _simpleValue;
static readonly Lazy<Task<int>> MySharedAsyncInteger = new Lazy<Task<int>>(
async () =>
{
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
return _simpleValue++;
});
async Task GetSharedIntegerAsync()
{
int sharedValue = await MySharedAsyncInteger.Value;
}
No matter how many parts of the code call Value simultaneously, the
Task<int> is only created once and returned to all callers.
But then he says :
If there are different thread types that may call Value (e.g., a UI
thread and a thread-pool thread, or two different ASP.NET request
threads), then it may be better to always execute the asynchronous
delegate on a thread-pool thread.
So he suggests the following code which makes the whole code run in a threadpool thread :
static readonly Lazy<Task<int>> MySharedAsyncInteger = new Lazy<Task<int>>(() => Task.Run(
async () =>
{
await Task.Delay(TimeSpan.FromSeconds(2));
return _simpleValue++;;
}));
Question:
I don't understand what's the problem with the first code. The continuation would be executed in a threadpool thread (due to ConfigureAwait , we don't need the original context).
Also as soon that any control from any thread will reach the await , the control will be back to the caller.
I don't see what extra risk the second code is trying to resolve.
I mean - what is the problem with "different thread types that may call Value" in the first code?
what is the problem with "different thread types that may call Value"
in the first code?
There in nothing wrong with that code. But, imagine you had some CPU bound work along with the async initialization call. Picture it like this for example:
static readonly Lazy<Task<int>> MySharedAsyncInteger = new Lazy<Task<int>>(
async () =>
{
int i = 0;
while (i < 5)
{
Thread.Sleep(500);
i++;
}
await Task.Delay(TimeSpan.FromSeconds(2));
return 0;
});
Now, you aren't "guarded" against these kind of operations. I'm assuming Stephan mentioned the UI thread because you shouldn't be doing any operation that's longer than 50ms on it. You don't want your UI thread to freeze, ever.
When you use Task.Run to invoke the delegate, you're covering yourself from places where one might pass a long running delegate to your Lazy<T>.
Stephan Toub talks about this in AsyncLazy:
Here we have a new AsyncLazy<T> that derives from Lazy<Task<T>> and
provides two constructors. Each of the constructors takes a function
from the caller, just as does Lazy<T>. The first constructor, in
fact, takes the same Func that Lazy<T>. Instead of passing that
Func<T> directly down to the base constructor, however, we instead
pass down a new Func<Task<T>> which simply uses StartNew to run the
user-provided Func<T>. The second constructor is a bit more fancy.
Rather than taking a Func<T>, it takes a Func<Task<T>>. With this
function, we have two good options for how to deal with it. The first
is simply to pass the function straight down to the base constructor,
e.g:
public AsyncLazy(Func<Task<T>> taskFactory) : base(taskFactory) { }
That option works, but it means that when a user accesses the Value
property of this instance, the taskFactory delegate will be invoked
synchronously. That could be perfectly reasonable if the taskFactory
delegate does very little work before returning the task instance.
If, however, the taskFactory delegate does any non-negligable work, a
call to Value would block until the call to taskFactory completes. To
cover that case, the second approach is to run the taskFactory using
Task.Factory.StartNew, i.e. to run the delegate itself asynchronously,
just as with the first constructor, even though this delegate already
returns a Task<T>.