I have this code :
var task = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
// Code...
Invoke(new Action(() => progressBar.Increment(1)));
// Code...
});
task.Wait();
But the Invoke fail, without Exception or any kind of error.
It seems that the "wait" prevents the refresh of the form, probably because I'm still in the method.
how do I get around this?
Thanks
You got yourself a dead-lock.
When the Task is running (on a different thread) and you call Invoke, it wants to invoke it on the mainthread. But the mainthread is waiting for the Task to complete... (task.Wait() will block until it's ready)
What if you use:
await task;
The method using this code should be marked as async. The compiler will cut the method into pieces, and while waiting, the messageloop/thread runs again. When the task is ready, the rest of the method will be executed. (below the await task;)
Look here for more info: await vs Task.Wait - Deadlock?
This is a deadlock. The UI thread is blocking on the task.Wait() line, waiting for the task to finish. The task is blocking on Invoke because it needs to tell the UI thread to update the progress bar.
You should NOT be waiting for a task to complete on the UI thread, and should remove task.Wait(). The UI will update as soon as the task finishes.
Any code you were going to put below task.Wait() should go inside the Invoke action:
var task = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
// do task work
Invoke(new Action(() => {
progressBar.Increment(1);
// other code that needs the task to be finished should go here
}));
});
// don't call task.Wait() here
Related
TLDR: In my example (ASP.NET) below why does task1.Result and task2.Result result in a deadlock and task3.Result does not?
We have a class in our code, where I cannot easily mark the method as async and keep the code from blocking while waiting for an async task to finish. The reason is that our framework does not support that. Therefore I tried to find a solution with task.Result and got some deadlocks. Luckily I found a solution (see task3). Now I tried to find out, what is the difference between task1, task2 and task3 to understand why the first two result in a deadlock and the third does not.
Using the debugger I did not see any difference like task3 being run before task3.Result is called. It is still in WaitingForActivation state like the other two. Can anyone explain to me, how task3 can work?
public class HomeController : Controller
{
public ActionResult GetSomething()
{
var task1 = GetSomethingAsync();
var task2 = Task.Run(async () => await task1);
var task3 = Task.Run(async () => await GetSomethingAsync());
return Content(task1.Result);
// return Content(task2.Result);
// return Content(task3.Result);
}
private static async Task<string> GetSomethingAsync()
{
return await Task.Run(() => "something");
}
}
The root of the problem is the await here:
private static async Task<string> GetSomethingAsync()
{
return await Task.Run(() => "something");
}
The context is captured before entering the awaiting, and the context is the main thread. So after the awaiting the context must be restored, so the continuation is scheduled to run in the main thread. Since the main thread is blocked at this point, it can't process the continuation, hence the deadlock.
To prevent the capturing of the context you could configure this await with ConfigureAwait(false).
Update: By continuation I mean the code inside GetSomethingAsync that follows after the awaiting. Although there is no code after that, it seems that the compiler does bother to create an actual continuation for this no-op part of the method (otherwise a deadlock should not occur in your example).
It should be noted that the compiler transforms an async method to a Task that consists of multiple mini-tasks. Every await encountered in the path of the execution causes the creation of a mini-task that is the continuation of the awaited task. All these mini-tasks are completed one after the other, and the completion of the last one signals the completion of the "master-task" that is returned by the async method.
What ever GetSomethingAsync() does it is done by the calling thread until some operation (OP) can not be completed right away (for example io) then the controlflow is given to the calling function but.
If you then access the Result property on the returned Task object the thread will be blocked.
This leads to the problem that even is the OP is finished the thread will not know about it because he is busy waiting for the completion of the Task
If however you let GetSomethingAsync() be exectuted by some thread-pool thread (which Task.Run(...) does) the thread-pool thread can finish the OP and the calling thread can be notified that the Task has completed.
Update:
Your second approch does not work because the task was still started on your main thread. If you have this methode
public static async Task DoStuffAsync()
{
Console.WriteLine($"Doing some stuff1 on thread {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(50);
Console.WriteLine($"Doing some stuff2 on thread {Thread.CurrentThread.ManagedThreadId}");
}
and run this code in an appilcation with an SynchronizationContext
var task = DoStuffAsync();
Console.WriteLine($"Doing main stuff on thread {Thread.CurrentThread.ManagedThreadId}");
await Task.Run(async () => await task);
It will output something like:
Doing some stuff1 on thread 1
Doing main stuff on thread 1
Doing some stuff2 on thread 1
So with the code line Task.Run(async () => await task) you only achieved that a thread-pool thread waits on the completion of your original Task, but this in turn creates a new Task that if not handeld by awaiting it causes a deadlock.
There are following methods,
async Task DoWork1Async() { .... };
async Task DoWork2Async() { .... };
async Task DoWork3Async() { .... };
I read the following code
await Task.Run(() => DoWork1Async());
await Task.Run(() => DoWork2Async());
await Task.Run(() => DoWork3Async());
instead of
await DoWork1Async();
await DoWork2Async();
await DoWork3Async();
What's the difference between these two?
When you run (within a method marked async)
await DoWork1Async();
your code calls DoWork1Async within a state machine the compiler sets up. At that point, you code relinquishes control back to that state machine. When the task completes, the rest of the code in your method continues.
Remember that async code doesn't necessarily run on a separate thread (for example, if you are doing asynchronous I/O).
When you run:
await Task.Run(() => DoWork1Async());
your DoWork1Async is dispatched as work to the Thread Pool. It is executed on a different thread (a thread pool thread). When that work is completed, that same state machine mechanism hands control back to you code to continue running.
In the second case, your code always runs on a thread pool thread. In the first case, you may not be using an extra thread at all (depending on how DoWork1Async is coded)
await Task.Run(() => DoWork1Async());
Starts a Task, which will call DoWork1Async. This is guaranteed to be asynchronous no matter how DoWork1Async is implemented.
Note: Task.Run(Action<Task<T>>) returns a Task<T>,
not a Task<Task<T>>. When your lambda returns a Task, Task.Run() returns a Task that completes with the result of the inner task. Thus you do not need to do awkward things like await await Task.Run(() => return a Task).
await DoWork1Async();
Calls DoWork1Async synchronously on the current thread. If DoWork1Async executes an await statement, then work will be suspended and the remainder of the work will occur asynchronously. However, if DoWork1Async completes execution without hitting an await, then control will return to your caller and will then start DoWork2Async all synchronously.
So in short, the first form guarantees the DoWork1Async won't start or finish synchronously.
The second form will start DoWork1Async synchronously, and may even finish it synchronously depending upon how it is written.
--
Here's a fiddle showing the difference:
https://dotnetfiddle.net/GhrO8x
Notice how in the first case DoWork() starts and executes completely synchronously before we even await its Task while in the 2nd case it executes asynchronously after we await its task.
I am using Task to create and perform some operations by a different thread, once the operation is done I also have called back to be called.
System.Threading.Tasks.Task.Factory.StartNew(() =>
this._httpService.CreateRecord(new Uri(Configuration.Current.CreateRecordUrl), httpObj)).ContinueWith(
(response) =>
{
if (!response.IsFaulted)
{
if (httpObj.CallBack != null)
{
httpObj.CallBack(response.Result);
}
}
else {
this._logger.Error("There was some error which causes the task to fail");
}
});
My console application's main thread is not waiting for the Task thread to complete, because it's background thread.
How can I make task thread foreground thread?
Thanks
StartNew() method returns a Task instance. Calling Wait() method on the returned task will block the main thread until the task finishes.
static void Main(string[] args)
{
var task = Task.Factory.StartNew(() =>
{
// ...
});
task.Wait(); // The main application thread waits here until the task returns
}
My console application's main thread is not waiting for the Task thread to complete, because it's background thread.
Your application is not waiting for the task, because you don't tell it to do so.
As others have already stated, use Wait/Result or await to wait for the task, depending on whether you're in an asynchronous context or not.
How can i make task thread foreground thread.
Most likely you don't want to do that in the first place. A background thread is a thread that terminates when all foreground threads have ended. Thread pool threads are inherently background threads, if you actually want to schedule your task to a foreground thread, that is, a thread that will keep the app process alive even if the main thread is finished, you'll have to create your own TaskScheduler. That, btw, would be a reason to use Task.Factory.StartNew. If you don't need Task.Factory.StartNew, go for Task.Run.
You should wait for completion of the Task in your main thread.
Change your code to
var task = System.Threading.Tasks.Task.Factory.StartNew(() =>
this._httpService.CreateRecord(new Uri(Configuration.Current.CreateRecordUrl), httpObj)).ContinueWith(
(response) =>
{
if (!response.IsFaulted)
{
if (httpObj.CallBack != null)
{
httpObj.CallBack(response.Result);
}
}
else {
this._logger.Error("There was some error which causes the task to field");
}
});
task.Wait(); // Wait till your Task has finished.
The Wait() method has some overloads to specify how long to wait. Also you have to add some exception handling if Task execution fails due to an exception of cancellation.
Try creating a fresh new Thread instead of taking from the pool. For eg:
Thread t = new Thread(()=>
{
//all your code goes here
});
t.IsBackground = false; //by default it will be foreground. so don't need this line in your case
t.Start();
This will create a foreground thread for u and it will make sure the thread completes its execution.
Task t = new Task(() =>
{
//I would expect this to be on a worker thread, but it's not!
Thread.Sleep(1000);
});
Task test = new Task(() =>
{
Thread.Sleep(1000);
});
test.ContinueWith(x =>
{
//Do some UI Updates here, but also start another Task running.
t.Start();
}, TaskScheduler.FromCurrentSynchronizationContext());
test.Start();
Why does t gets invoked on the UI Thread. I understand that I created a continuation Task against test which correctly gets called on the UI thread, but I am then starting a new task running. Now I know I could get around this by specifying TaskScheduler.Default as an overload method against t.Start, but why does a new Task get started on the ui thread?
but why does a new Task get started on the ui thread?
Because unless specified otherwise calling Start on a task schedules the task on the current TaskScheduler which in your case is a just facade over the UI thread's SynchronizationContext that you created using TaskScheduler.FromCurrentSynchronizationContext().
Starts the Task, scheduling it for execution to the current TaskScheduler.
From Task.Start Method
If you want that task to be scheduled on a different TaskScheduler than the current one you can pass it as a parameter:
t.Start(TaskScheduler.Defualt);
Note: There's almost no case imaginable that using Task.Start is the best solution for. You should probably rethink this avenue.
Don't use the Task.Start method. Also, if you want to delay a task use Task.Delay like this:
Task.Delay(TimeSpan.FromSeconds(1)) //Wait 1 second
.ContinueWith(t => DoSomeUIWork(), TaskScheduler.FromCurrentSynchronizationContext()) //execute something on the UI thread
.ContinueWith(t => DoSomeBackgroundWork()); //Then do some background work
I have just tested something that I was sure would fail miserably, but to my surprise, it worked flawlessly, and proves to myself that I am still quite mystified by how async-await works.
I created a thread, passing an async void delegate as the thread's body.
Here's an oversimplification of my code:
var thread = new Thread( async () => {
while( true ) {
await SomeLengthyTask();
...
}
});
thread.Start();
thread.Join();
The thing is that as far as I understand, when the execution hits the await keyword, there is an implicit return from the method, in this case the body of the looping thread, while the rest of the code is wrapped in a callback continuation.
Because of this fact, I was pretty sure that the thread would terminate as soon as the await yielded execution, but that's not the case!
Does anybody know how this magic is actually implemented? Is the async functionality stripped down and the async waits synchronously or is there some black magic being done by the CLR that enables it to resume a thread that has yielded because of an await?
The thread is indeed terminated very quickly.
But since the Thread constructor doesn't accept an async lambda what you got there is an async void delegate.
The original thread will end and the continuation (the rest after the await) will be posted to the ThreadPool and eventually run on another thread.
You can test that by checking the thread id:
var thread = new Thread(async () =>
{
while (true)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await SomeLengthyTask();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
});
thread.Start();
thread.Join();
Console.ReadLine();
Output:
3
5
5
...
5
To make the example simpler let's assume you have this Run method:
void Run(Action action)
{
action();
}
And you call it with your async delegate
Run(async () =>
{
while(true)
{
await SomeLengthyTask();
...
}
});
The execution of Run will complete almost immediately when it reaches the first await and returns. The rest of the async delegate will continue on the ThreadPool with another thread.
Generally, each time you reach an await in the execution of an async method the thread is lost and the continuation (the rest after the awaited task completes) will be posted to the ThreadPool (unless if there's a SynchronizationContext present, like in the UI thread). It may be that it execution will be on the same thread (as in my example with 5) but it also may not.
In your case the thread you create explicitly isn't part of the ThreadPool so it will definitely be terminated and the rest will run on a different thread.