I am having a task like below.
var task = Task<string>.Factory.StartNew(() => longrunningmethod()
.ContinueWith(a =>
longrunningmethodcompleted((Task<string>)a,
TaskScheduler.FromCurrentSynchronizationContext())));
task.Wait();
My task will call the longrunningmethod and after completing it will call completed method.
Inside my longrunningmethod I am delaying by Thread.Sleep(30000). When I use Task.wait system hangs and it's not calling longrunningmethodcompleted method. If I don't use Task.wait everything flows good.
I strongly suspect your context is a UI context.
In that case, you're causing the deadlock because you're telling longrunningmethodcompleted to execute on the current SynchronizationContext.
Then you're blocking that context by calling Wait. The continuation will never complete because it needs to execute on the thread that is blocked in Wait.
To fix this, you can't use Wait on a continuation running in that context. I'm assuming that longrunningmethodcompleted must run on the UI thread, so the solution is to replace the call to Wait with a call to ContinueWith:
var ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task<string>.Factory.StartNew(() => longrunningmethod()
.ContinueWith(a =>
longrunningmethodcompleted((Task<string>)a,
ui);
task.ContinueWith(..., ui);
Or, you can upgrade to VS2012 and use async/await, which lets you write much cleaner code like this:
var task = Task.Run(() => longrunningmethod());
await task;
longrunningmethodcompleted(task);
Well it is hard to tell what is wrong with your code without seeing what the actual asynch actions are, all I know is according to MSDN waits for the task to be completed. Is it possible that because you are trying to use the current SynchronizationContext your actions blocks?
The reason I am asking is because you
Start the taskWait for the task to complete (which is the continue with task)Task tries to continue with current SynchronizationContextTask tries to acquire the main threadTask scheduled to take the thread after the Wait is completedBut Wait is waiting on current Task to complete (deadlock)
What I mean is that the reason your program works with Thread.Sleep(seconds) is because after the time limit is up the thread will continue.
Thread.Sleep(nnn) is blocking. Use Task.Delay(nnn) and await:
await Task.Delay(30000);
Edited to add: Just noted the tag says C# 4. This requires C# 5 and the new async await support. Seriously, if you're doing async and tasks, you need to upgrade.
Related
I want to get the thread of a task that is running and not completed. The language I am using is c#, and what I am trying to do is if some action cannot be completed which is locking one of my file, in that case I want to get the thread of that action and destroy the thread and release the file. thats what I want to do.
var task= Task.Run(() => SomeFunction){
getting thread code for the incomplete task here}
Did you mean the Id?
I think you can access it by Task.CurrentId
As stated on this document.
As for completion, you can use Task.IsCompleted.
As states this document.
I have a method that produces an array of tasks (See my previous post about threading) and at the end of this method I have the following options:
await Task.WhenAll(tasks); // done in a method marked with async
Task.WhenAll(tasks).Wait(); // done in any type of method
Task.WaitAll(tasks);
Basically I am wanting to know what the difference between the two whenalls are as the first one doesn't seem to wait until tasks are completed where as the second one does, but I'm not wanting to use the second one if it's not asynchronus.
I have included the third option as I understand that this will lock the current thread until all the tasks have completed processing (seemingly synchronously instead of asynchronus) - please correct me if I am wrong about this one
Example function with await:
public async void RunSearchAsync()
{
_tasks = new List<Task>();
Task<List<SearchResult>> products = SearchProductsAsync(CoreCache.AllProducts);
Task<List<SearchResult>> brochures = SearchProductsAsync(CoreCache.AllBrochures);
_tasks.Add(products);
_tasks.Add(brochures);
await Task.WhenAll(_tasks.ToArray());
//code here hit before all _tasks completed but if I take off the async and change the above line to:
// Task.WhenAll(_tasks.ToArray()).Wait();
// code here hit after _tasks are completed
}
await will return to the caller, and resume method execution when the awaited task completes.
WhenAll will create a task When All all the tasks are complete.
WaitAll will block the creation thread (main thread) until all the tasks are complete.
Talking about await Task.WhenAll(tasks) vs Task.WhenAll(tasks).Wait(). If execution is in an async context, always try to avoid .Wait and .Result because those break async paradigm.
Those two blocks the thread, nothing other operation can take it. Maybe it is not a big problem in small apps but if you are working with high demand services that is bad. It could lead to thread starvation.
In the other hand await waits for the task to be completed in background, but this does not block the thread allowing to Framework/CPU to take it for any other task.
Is there any framework support for the cases when application is going to close but there are some not completed tasks?
Tasks run in the context of background thread by default. Sometimes it's ok just to let the task complete:
Task.Factory.StartNew(() =>
{
Thread.CurrentThread.IsBackground = false;
Thread.Sleep(20000);
Thread.CurrentThread.IsBackground = true;
});
But this doesn't work if task has continuations which require completition. Especially if some of the tasks will run under UI thread.
It is possible to get all the "final" tasks and to postpone the application exit with WhenAll().
Yet I do not know how to do the same when async/await is used.
So I'd like to know if there's any support for such cases. Are there any guarantees which framework gives or ways to enforce them?
The only way I see now is setting flags as a sign that critical tasks are not completed yet.
As an aside, you should not set IsBackground on a thread pool thread.
For async methods, ensure your methods are returning Task and not void, and then you can await them all using WhenAll. You can have your event handlers capture the top-level Tasks rather than await them.
Trying to understanding the difference between the TPL & async/await when it comes to thread creation.
I believe the TPL (TaskFactory.StartNew) works similar to ThreadPool.QueueUserWorkItem in that it queues up work on a thread in the thread pool. That's of course unless you use TaskCreationOptions.LongRunning which creates a new thread.
I thought async/await would work similarly so essentially:
TPL:
Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith(
(antecedent) => {
DoSomeWorkAfter();
},TaskScheduler.FromCurrentSynchronizationContext());
Async/Await:
await DoSomeAsyncWork();
DoSomeWorkAfter();
would be identical. From what I've been reading it seems like async/await only "sometimes" creates a new thread. So when does it create a new thread and when doesn't it create a new thread? If you were dealing with IO completion ports i can see it not having to create a new thread but otherwise I would think it would have to. I guess my understanding of FromCurrentSynchronizationContext always was a bit fuzzy also. I always throught it was, in essence, the UI thread.
I believe the TPL (TaskFactory.Startnew) works similar to ThreadPool.QueueUserWorkItem in that it queues up work on a thread in the thread pool.
Pretty much.
From what i've been reading it seems like async/await only "sometimes" creates a new thread.
Actually, it never does. If you want multithreading, you have to implement it yourself. There's a new Task.Run method that is just shorthand for Task.Factory.StartNew, and it's probably the most common way of starting a task on the thread pool.
If you were dealing with IO completion ports i can see it not having to create a new thread but otherwise i would think it would have to.
Bingo. So methods like Stream.ReadAsync will actually create a Task wrapper around an IOCP (if the Stream has an IOCP).
You can also create some non-I/O, non-CPU "tasks". A simple example is Task.Delay, which returns a task that completes after some time period.
The cool thing about async/await is that you can queue some work to the thread pool (e.g., Task.Run), do some I/O-bound operation (e.g., Stream.ReadAsync), and do some other operation (e.g., Task.Delay)... and they're all tasks! They can be awaited or used in combinations like Task.WhenAll.
Any method that returns Task can be awaited - it doesn't have to be an async method. So Task.Delay and I/O-bound operations just use TaskCompletionSource to create and complete a task - the only thing being done on the thread pool is the actual task completion when the event occurs (timeout, I/O completion, etc).
I guess my understanding of FromCurrentSynchronizationContext always was a bit fuzzy also. I always throught it was, in essence, the UI thread.
I wrote an article on SynchronizationContext. Most of the time, SynchronizationContext.Current:
is a UI context if the current thread is a UI thread.
is an ASP.NET request context if the current thread is servicing an ASP.NET request.
is a thread pool context otherwise.
Any thread can set its own SynchronizationContext, so there are exceptions to the rules above.
Note that the default Task awaiter will schedule the remainder of the async method on the current SynchronizationContext if it is not null; otherwise it goes on the current TaskScheduler. This isn't so important today, but in the near future it will be an important distinction.
I wrote my own async/await intro on my blog, and Stephen Toub recently posted an excellent async/await FAQ.
Regarding "concurrency" vs "multithreading", see this related SO question. I would say async enables concurrency, which may or may not be multithreaded. It's easy to use await Task.WhenAll or await Task.WhenAny to do concurrent processing, and unless you explicitly use the thread pool (e.g., Task.Run or ConfigureAwait(false)), then you can have multiple concurrent operations in progress at the same time (e.g., multiple I/O or other types like Delay) - and there is no thread needed for them. I use the term "single-threaded concurrency" for this kind of scenario, though in an ASP.NET host, you can actually end up with "zero-threaded concurrency". Which is pretty sweet.
async / await basically simplifies the ContinueWith methods ( Continuations in Continuation Passing Style )
It does not introduce concurrency - you still have to do that yourself ( or use the Async version of a framework method. )
So, the C# 5 version would be:
await Task.Run( () => DoSomeAsyncWork() );
DoSomeWorkAfter();
I'm just wondering whether the new Task class in dot.net 4 is creating a background or foreground thread ?
Normally I'd set "IsBackground" on a Thread, but there's no such attribute on a Task.
I've not been able to find any documentation of this on MSDN :-(
Shouldn't be tough to verify:
class Program
{
static void Main()
{
Task
.Factory
.StartNew(() => Console.WriteLine(Thread.CurrentThread.IsBackground))
.Wait();
}
}
And the answer is ...
ǝnɹʇ
If you are starting a Task<T> using Task.Run(), then yes.
If you are using async and await, then no. Excerpt from here:
"The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available."
It appears to run as a background thread.
See this thread:
Running multiple C# Task Async
Tasks are executed by threads which are coming from the system thread pool. A thread that comes from thread pool is executed in background by default.
If you are not yet convinced of a background task, just try to access a GUI element from within a Task like:
public async Task<int> ProcessStuff_Async()
{
while(true)
{
label1.Text = "processing next item";
to get the run time exception:
Cross-thread operation not valid:
Control 'label1' accessed from a thread other than the thread it was created on.
just like with the good old regular background threads.
There is info in MSDN docs (as of 2017 :-) , e.g.:
The best way to handle this ... is to start a background thread which
does the work using Task.Run, and await its result. This will allow
the UI to feel smooth as the work is being done.
This doc even has a section What happens under the covers.