I was under the impression that I could just make this thread call and whatever was in my method "DoSomething" would just start happening, but apparently not.
When I invoke this line:
Task.Factory.StartNew(() =>
ControllerClass.DoSomething("data"),
CancellationToken.None,
TaskCreationOptions.LongRunning, TaskScheduler.Default);
ControllerClass.DoSomething("data") is not executed.
However, if I add a Wait, then the method gets called.
The reason I'm using the LongRunning option is that the method can be LongRunning in certain things aren't in place when it start executing. And yes, the the method itself works when called inline. It is just that it needs to be in a thread so that the main program can continue while this thread does its thing.
By the way, I have also tried this way to call it and same results:
Task.Factory.StartNew(() =>
ControllerClass.DoSomething("data")).ContinueWith
(t =>
{
SendErrorEmail(t.Exception);
}, TaskContinuationOptions.OnlyOnFaulted
);
Am I missing some option to tell it to start executing the method call right away?
I was under the impression that I could just make this thread call and
whatever was in my method "DoSomething" would just start happening,
but apparently not.
No, this is not happening. Actually, when you write this:
Task.Factory.StartNew(() =>
ControllerClass.DoSomething("data"),
CancellationToken.None,
TaskCreationOptions.LongRunning, TaskScheduler.Default);
under the cover your task is get into a queue and sooner or later will be run on a thread of the ThreadPool.
According to MSDN:
Calling StartNew is functionally equivalent to creating a
Task using one of its constructors and then calling Start to
schedule it for execution.
Ragarding you other statement:
However, if I add a Wait, then the method gets called.
This is true, because the TaskFactory.StartNew returns a Task object. when we call the Wait method of a task
If the current task has not started execution, the Wait method
attempts to remove the task from the scheduler and execute it inline
on the current thread. If it is unable to do that, or if the current
task has already started execution, it blocks the calling thread until
the task completes.
In a few words Wait is a blocking action.
Please have a look here for more information on this.
Am I missing some option to tell it to start executing the method call
right away?
No. Unless calling wait there isn't any alternative, as far as I am aware of.
Related
The reason for what I'm going to ask here is that Dispatcher.Invoke throws a TaskCanceledException when another thread executes Dispatcher.InvokeShutdown(). Dispatcher.BeginInvoke() does not seem to suffer from this and I wanted to move my codebase from using Dispatcher.Invoke(...) to Dispatcher.BeginInvoke(...). And below I wanted to ask if the following two Work() methods both running on a separate background thread are equivalent? (do any of you see any issues changing the first into the second?):
Work(){
Dispatcher.Invoke(() => {sameFunction()});
//more work
...
}
Work(){
var task = Dispatcher.BeginInvoke((Action)(() => {sameFunction()});
task.Wait();
//more work
...
}
This issue is a direct consequence of the following issue's answer not having functioned as hoped for. It seems that once Dispatcher.InvokeShutdown has been called (once Dispatcher.HasShutdownStarted is true), all calls to Dispatcher.Invoke will end in throwing a TaskCancelledException.
You should use Dispatcher.InvokeAsync instead of Dispatcher.BeginInvoke. BeginInvoke is part of the old API.
Also, never call Wait(), but use await:
await Dispatcher.InvokeAsync()
Using the new API also allows you to cancel operations (Invoke and InvokeAsync only): to fix the exception issue, you should provide a shared CancellationToken, that you associate with the Dispatcher (virtually, with the one you expect to get shutdown), to every invocation.
This way you can cancel the pending and running operations gracefully before you shutdown the Dispatcher.
Dispatcher.InvokeShutdown will abort any running Dispatcher operation, which applies to every synchronous Dispatcher.Invoke execution - hence the TaskCanceledException is being thrown on abortion.
Regarding Dispatcher.InvokeAsync (and Dispatcher.BeginInvoke): your probably don't experience the cancellation exception, because the dispatched operation is still pending due to its asynchronous execution.
This leads to the difference of both Dispatcher invocation examples:
Your first example uses Dispatcher.Invoke. From the documentation you could learn that it executes synchronously. This means, the delegate is executed immediately (pushed to the front of the queue - respecting the assigned priorities).
The second example uses Dispatcher.BegingInvoke (same applies to the modern Dispatcher.InvokeAsync). This method invokes the delegate asynchronously. This means, the delegate is enqueued into the dispatcher queue and executed after all preceeding pending operations in this queue are completed. If you don't await the call, the Dispatcher returns immediately after enqueuing the delegate and execution continues (this is the asynchronous part).
Therfore, the examples are not equivalent. You have to decide if postponing the delegate's execution is reasonable (Dispatcher.InvokeAsync) or not (Dispatcher.Invoke).
var task = Task.Run(() => DoSomeStuff()).Result;
What happens here under the hood?
I made a tiny test:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
var r = Task.Run( () => {Thread.Sleep(5000); return 123; }).Result;
Console.WriteLine(r);
}
}
It prints "123" after 5s. So does accessing any such property on Task act as a shortcut to calling Task.Wait() i.e. is this safe to do?
Previously my code called Task.Delay(5000) which returned "123" immediately. I fixed this in my question but leave this here as comments and answers reference it.
You asked two questions. First, does accessing Result implicitly cause a synchronous Wait? Yes. But the more important question is:
is this safe to do?
It is not safe to do this.
It is very easy to get into a situation where the task that you are synchronously waiting on has scheduled work to run in the future before it completes onto the thread that you just put to sleep. Now we have a situation where the thread will not wake up until the sleeping thread does some work, which it never does because it is asleep.
If you already know that the task is complete then it is safe to synchronously wait for the result. If you do not, then it is not safe to synchronously wait.
Now, you might say, suppose I know through some other means that it is safe to wait synchronously for an incomplete task. Then is it safe to wait? Well, by the assumption of the question, yes, but it still might not be smart to wait. Remember, the whole point of asynchrony is to manage resources efficiently in a world of high latency. If you are synchronously waiting for an asynchronous task to complete then you are forcing a worker to sleep until another worker is done; the sleeping worker could be doing work! The whole point of asynchrony is to avoid situations where workers go idle, so don't force them to.
An await is an asynchronous wait. It is a wait that means "wait on running the rest of the current workflow until after this task is done, but find something to do while you are waiting". We did a lot of work to add it to the language, so use it!
So does accessing any such property on Task act as a shortcut to calling Task.Wait()?
Yes.
From the docs:
Accessing the [Result] property's get accessor blocks the calling thread until the asynchronous operation is complete; it is equivalent to calling the Wait method.
However, your test doesn't do what you think it does.
Task.Delay(..) returns a Task which completes after the specified amount of time. It doesn't block the calling thread.
So () => { Task.Delay(5000); return 123; } simply creates a new Task (which will complete in 5 seconds), then throws it away and immediately returns 123.
You can either:
Block the calling thread, by doing Task.Delay(5000).Wait() (which does the same thing as Thread.Sleep(5000))
Asynchronously wait for the Task returned from Task.Delay to complete: Task.Run(async () => { await Task.Delay(5000); return 123; })
The test doesn't wait for Task.Delay() so it returns immediatelly. It should be :
var r = Task.Run(async () => { await Task.Delay(5000); return 123; }).Result;
The behavior of Result is well defined - if the task hasn't completed, it blocks until it does. Accessing other Task properties doesn't block
I have read a lot of articles and still cant get understand this part.
Consider this code :
private async void button1_Click(object sender, EventArgs e)
{
await Dosomething();
}
private async Task<string> Dosomething()
{
await Task.Run((() => "Do Work"));
return "I am done";
}
First question:
When I click the button, it will Call DoSomething and await a Task that creates a Thread from the threadpool by calling Task.Run ( if I am not mistaken ) and all of this runs asynchronously. So I achieved creating a thread that does my work but doing it asynchronously? But consider that I don't need any result back, i just want the work to be done without getting any result back, is there really a need to use async/await , and if so, how?
Second question:
When running a thread asynchronously, how does that work? Is it running on the main UI but on a separate thread or is it running on a separate thread and separate is asynchronously inside that method?
The purpose of creating Async methods is so you can Await them later. Kind of like "I'm going to put this water on to boil, finish prepping the rest of my soup ingredients, and then come back to the pot and wait for the water to finish boiling so I can make dinner." You start the water boiling, which it does asynchronously while you do other things, but eventually you have to stop and wait for it. If what you want is to "fire-and-forget" then Async and Await are not necessary.
Simplest way to do a fire and forget method in C#?
Starting a new task queues that task for execution on a threadpool thread. Threads execute in the context of the process (eg. the executable that runs your application). If this is a web application running under IIS, then that thread is created in the context of the IIS worker process. That thread executes separately from the main execution thread, so it goes off and does its thing regardless of what your main execution thread is doing, and at the same time, your main execution thread moves on with its own work.
1
There's a big difference if you don't await the Task or you await it:
Case you don't await it: DoSomething is called but next sentence is executed while DoSomething Task hasn't been completed.
Case you await it: DoSomething is called and next sentence is executed once DoSomething Task has been completed.
So, the need of async/await will depend on how you want to call DoSomething: if you don't await it is like calling it the fire & forget way.
2
Is it running on the main UI but on a separate thread or is it running
on a seperate thread and separate is asynchronously inside that
method?
Asynchronous code sometimes means other thread (see this Q&A Asynchronous vs Multithreading - Is there a difference?). That is, either if the code is being executed in a separate thread from the UI one or it lets continue the processing of the UI thread while it gets resumed, it's nice because UI loop can still update the screen while other tasks are being done in parallel without freezing the UI.
An asynchronous method (i.e. async method) is a syntactic sugar to tell the compiler that await statements should be treated as a state machine. The C# compiler turns your async/await code into a state machine where code awaiting a Task result is executed after the code that's being awaited.
Interesting Q&As
You might want to review these other Q&As:
Async/Await vs Threads
What's the difference between Task.Start/Wait and Async/Await?
async/await - when to return a Task vs void?
Is Async await keyword equivalent to a ContinueWith lambda?
OP said...
[...] But does this mean that "async/await" will fire off a thread and
Task.Run also fires off a thread or are they both the same thread?
Using async-await doesn't mean "I create a thread". It's just a syntactic sugar to implement continuations in an elegant way. A Task may or may not be a thread. For example, Task.FromResult(true) creates a fake task to be able to implement an async method without requirement it to create a thread:
public Task<bool> SomeAsync()
{
// This way, this method either decides if its code is asynchronous or
// synchronous, but the caller can await it anyway!
return Task.FromResult(true);
}
The type Task<TResult> requires you to return a TResult from your task. If you don't have anything to return, you can use Task instead (which, incidentally, is the base class of Task<TResult>).
But keep in mind that a task is not a thread. A task is a job to be done, while a thread is a worker. As your program runs, jobs and workers become available and unavailable. Behind the scenes, the library will assign your jobs to available workers and, because creating new workers is a costly operation, it will typically prefer to reuse the existing ones, through a thread pool.
I am using monotouch/Xamarin for an iOS app.
The documentation for Task.Run states:
Queues the specified work to run on the ThreadPool and returns a task
handle for that work.
Which essentially indicates that it could run on any thread ThreadPool.
I want to do something like:
Task.Run(async () => await PerformTask());
but have it run on the main thread. Normally I would write it using BeginInvokeOnMainThread as follows:
BeginInvokeOnMainThread(async () => await PerformTask());
But I am doing this in shared code and do not want to use iOS specific calls. Is there a way for me to tell Task.Run() to invoke the action on the main thread?
If you want to run PerformTask in the current thread, instead of a thread pool thread, you simply need to not call Task.Run. Just use:
PerformTask();
and you're done. If you want to only continue executing the rest of the method when that task is done, then await it:
await PerformTask();
There is no reason to call Task.Run here for you, nor is there any reason to create a lambda that awaits the method for no particular reason (you could just call it directly if you wanted to start it from a thread pool thread).
If you want to run a task from the main thread you could use TaskSchedluer's method FromCurrentSynchronizationContext().
Task t = new Task(() =>
{
...
});
t.Start(TaskScheduler.FromCurrentSynchronizationContext());
This can be useful sometimes. However, if you want to use this technique to bypass thread checks (for example, modifying properties of form controls in a windows app), you should rethink your design. Use tasks for calculations or other non-UI operations and update the UI from the main thread.
Have a look at MainQueue.cs: https://gist.github.com/gering/0aa9750d3c7d14b856d0ed2ba98374a8
It is for Xamarin Forms applications. You have to call Init() from main thread once, but then you are able to ensure execution on main thread.
When you create a Task while specifying TaskCreationOptions.LongRunning a new thread is created specifically for the task. If you do not specify the TaskCreationOptions.LongRunning then the threadpool is used.
Please correct me if I'm wrong but if the threadpool is used you do not need to dispose() the task (as long as you have not used any synchronisation objects inside the task, like Wait() on a child task).
If this is the case, am I responsible for cleaning up the extra thread created by using the TaskCreationOptions.LongRunning flag?
If so is the following an acceptable pattern:
var task = Task.Factory.StartNew(() => {...}, TaskCreationOptions.LongRunning);
task.ContinueWith(x => task.Dispose());
Notice how, the ContinueWith does not have a TaskContinuationOptions.LongRunning, so it should use the threadpool.
That being said, however, I have read that the thread that moves the state of the task to Completed, Faulted or Cancelled has a high change of running the continuation.
If someone could shine some light on this I would really appreciate it.
Definitely don't call Dispose() in a continuation - when are you going to dispose the continuation task?
AFAIK, the only reason Task is disposable is to clear up the wait handle created if you wait on the task. If you don't wait on the task, the wait handle will never be created. In any case, the finalizer will clear up eventually.
Also, if a new thread is created by the Task, it will clean up after itself.
TaskContinuationOptions.LongRunning is a hint to the Task factory/scheduler, things are not so fixed as you portray it.
I would expect the ContinueWith to be executed on the same (longRunning) Thread, that may or may not be running on the ThreadPool.
And as far as I know cleanup of Tasks is automatic, so I wouldn't bother with Dispose() here.
I'm not certain about the disposal of Tasks created with the LongRunning option but there are a few things that come to mind about the pattern you've shown.
As shown the initial long-running Task is not observed which means that if the operation throws an Exception for any reason, then it will end up being re-thrown in the Finalizer which would cause the process to crash.
The documentation for the Task says that you shouldn't call Dispose unless the Task has actually Completed. So really so you should be checking that Task is completed in the continuation if you're going to call dispose.
You're actually calling Dispose on the Task returned by ContinueWith not the original, long-running Task.
So you could do something like:
var task = Task.Factory.StartNew(() => {...}, TaskCreationOptions.LongRunning)
.ContinueWith(x =>
if(x.IsFaulted)
{
x.Exception.Handle(_ => true); //just an example, you'll want to handle properly
}
else if(x.IsCompleted)
{
//do something with the result, if necessary
x.Dispose());
});
Ultimately, I think that is more important to observe the Task than to Dispose it.