I have multi thread program with C# language.
When load main form, 4 thread start that all of them work with while(true)
Every thread run, active and exist in thread list but after 30 ms, one of thread (without any error) disappear from thread list and doesn't work
even breakpoint not work.
I want read data from TCP and process 3 steps then save to database
Task1: have while(true) and read data from tcp and add to blockingcollection bk1
Task 2: in while(true), take data from bk1 and process data then add data to BlockingCollection bk2
Task3 in while(true) take data from bk2 and process then bk3
Task 4 in while (true) take data from bk3 then insert database
I define task:
Task.Factory.StartNew(() => myfunction, CancellationToken.None,
TaskCreationOptions.PreferFairness, TaskScheduler.Default);
When click button1 all of tasks start and work correctly after some time task3 change status to RanToCompletion and does not work I didn't use async and await in code because task works parallel and don't need wait for other task.
Even TaskCreationOptions set to LongRunning
My function have while(true) and work producer-consumer method.
Please help me about problem.
Thanks for attention.
Your code never awaits that task to end. Use await and Task.Run instead:
await Task.Run(()=>myFunction());
or
await Task.Run(myFunction);
Tasks aren't threads. They're a job that gets executed by a threadpoool thread. Creating a thread is an expensive operation. To avoid the cost of creating and destroying threads, .NET keeps a pool of worker threads. Jobs, in the form of Action or Func delegates, get posted to that ThreadPool and executed by one of the worker threads.
Task.Run or Task.Factor.StartNew post a job to the threadpool for execution and return a Task, essentially a "promise" object. This means the calling thread isn't blocked waiting for the task to complete and can do other work. await makes it easy to await for that task to complete and get back to the calling thread. Once the task completes, execution can resume with the code after await.
In a desktop application that means the UI thread doesn't get blocked waiting for a task to complete and can keep processing Windows messages, button clicks, refresh its windows etc. When the task completes, execution will resume on the UI thread with the code that comes after await.
async void btn1_Click(object sender,EventArgs args)
{
var customerName=txtCustomer.Text;
var orders=await Task.Run(()=>LoadOrdersFromDbAsync(customerName));
grdOrders.DataSource=orders;
}
Related
I has spend a lot of time to understand async programming principles. But one thing is still unclear. I was confused by this code :
static async Task Method()
{
Console.WriteLine($"Method entered.");
await Task.Delay(1000);
Console.WriteLine($"Await 1 finished.");
await Task.Delay(1000);
Console.WriteLine($"Await 2 finished");
}
static int Main(string[] args)
{
Console.WriteLine($"Main started.");
return AsyncContext.Run(() => MainAsync(args));
}
static async Task<int> MainAsync(string[] args)
{
var t = Method();
Console.WriteLine("Thread starting sleep.");
Thread.Sleep(10000);
Console.WriteLine("Thread stopped sleeping");
Console.WriteLine(t.IsCompleted ? "Method completed" : "Method not completed");
await t;
return 0;
}
Result :
Main started.
Method entered.
Thread starting sleep.
Thread stopped sleeping
Method not completed
Await 1 finished.
Await 2 finished
As I understand while Main thread is sleeping IO-bound operations from Method should be executed (cause Task.Delay emulate IO) and interrupt Main thread sequentially to continue execute Method code.
So I expect to see:
Main started.
Method entered.
Thread starting sleep.
Await 1 finished.
Await 2 finished
Thread stopped sleeping
Method completed
I know that by Thread.Sleep I am making to stop Main thread. But as I understand Method() should not need thread because it consists of IO-bound operations.
Can anybody explain where I am misunderstanding it?
AsynContext that I am using is (here).
By default "await" captures the current synchronization context and spawns the continuation in that original context.
If the context is undefined, continuation is spawned in the default thread pool (TaskScheduler.Default).
I'm not familiar with AsyncContext, but it probably spawns MainAsync under some well synchronization context and since Thread.Sleep blocks the thread that occupies that context, the continuation of "await" will wait until the context is freed.
This is not a strange phenomenon, you can reproduce it without the AsyncContext class. Try to run the same code in a Windows forms application and you will see.
Windows forms have it's own synchronization context that guards against unsynchronized Control manipulation.
To overcome this, you could tell "await" to not capture the synchronization context by using the ConfigureAwait(false) method.
static async Task Method()
{
Console.WriteLine($"Method entered.");
await Task.Delay(1000).ConfigureAwait(false);
Console.WriteLine($"Await 1 finished.");
await Task.Delay(1000).ConfigureAwait(false);
Console.WriteLine($"Await 2 finished");
}
await won't try to spawn continuation in the existing context, rather it would spawn it in a thread pool task.
Why your code is behaving correctly as expected ?
On using the AsyncContext.Run, you are providing an explicit context for Console application which otherwise have NULL Synchronization Context, now when you execute the following lines of code in MainAsync:
var t = Method();
Console.WriteLine("Thread starting sleep.");
Thread.Sleep(10000);
Then Method() starts executing, where on encountering the statement:
await Task.Delay(1000);
It cedes the control back to the caller, where you block the context by making the Thread Sleep for 10s Thread.Sleep(10000);, so now before this sleep is over the Continuation cannot take place in the Async method, since it waits for the Continuation context to be available, moment its free, then it starts executing the Continuation, but by that time it also complete the remaining statements in the MainAsync, which seems to be prioritized and response is as expected, it awaits only in the very end, in fact checking the Task status for any logic like t.IsCompleted is more of a code smell, better is only await t, which waits for the Task completion
There are two ways to get the behavior that you expect
As shown by #Arik, configure both await using ConfigureAwait(false), what does this means, simple that for running the Async continuation it doesn't need the original context and that will continue as true Async operation, hence will provide the result as you expect. Most of the libraries wit Async functions especially IO based, implement ConfigureAwait(false).
Make the call from the Main as return MainAsync(args).Result;, this will ensure standard behavior of the Console applications, which means NULL Synchronization Context, which means Async doesn't care about continuation on any existing Context, it goes on in background even when you are making the Thread sleep, since it doesn't expect that context and the result would be same as you expect
Main started.
Method entered.
Thread starting sleep.
Await 1 finished.
Await 2 finished
Thread stopped sleeping
Method completed
0
AsyncContext schedules all tasks to be executed on a single thread. Your Method consists of Delays and WriteLines. You may think of Delays as analogous to IO operations in that they do not need a thread to be executed on. However, WriteLine requires a thread. Thus, when Method is awaken from Delay it waits for thread be available to execute WriteLine.
Actually the Method would block even if it does not contain WriteLines but only Delays because it needs a thread for the Delay to return to and to start new Delay, but that would be more difficult to notice without WriteLines.
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'm trying to understand async/await and have read a number of articles but am still confused about the synchronous/asynchronous nature.
I have the following test console app:
static void Main(string[] args)
{
var test = FooAsync();
Console.WriteLine("After FooAsync");
for (int i = 0; i < 100; i++)
Console.WriteLine("After that");
Console.ReadKey();
}
private static async Task FooAsync()
{
Console.WriteLine("Before delay");
await Task.Delay(1);
Console.WriteLine("After delay");
}
The code gives output along the lines of:
Before delay
After FooAsync
After that
After that
After that
After that
After delay
After that
.
.
I understand that async/await will not create a separate thread for processing and that at the point FooAsync reaches the await Task.Delay(1) line it will return back to Main as the task will not yet have completed, however, as we are only running on a single thread can someone explain what triggers the FooAsync method to resume at some arbitrary point within Main before Main can then continue?
Update
I take it back and i3arnon and dariogriffo are correct. The code does use multiple threads (as I'd have seen before had looked in the debugger or done the obvious as kha suggested). I'd been confused by the Threads section on the following page https://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_Threads not realising that a "continuation" actually refers to a continuation task schedule to run as soon as the task being "awaited" finishes.
This isn't single threaded.
When the delay task completes the rest of the method is posted to the ThreadPool and runs concurrently with your main thread. The "trigger" here is the callback of the internal System.Threading.Timer being used inside Task.Delay.
This behaviour depends on the SynchronizationContext. In a UI environment this would have been posted to the same UI thread and would have to wait until that thread is free.
If you would have been waiting for the task returned from FooAsync then you would only have a single thread running each time.
Async/await may create new threads OR NOT, it depends of the nature of the operation.
If the operation is an IO (for example disks/network operations) probably is coded in a way it will not spin a new thread. You can read from here:
The async and await keywords don't cause additional threads to be created?
If you create your own Async operation and you create a thread, that's a different story, that's why you shouldn't do async over sync
http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx
You can check this also but using Thread.CurrentThread to get the Id of the process. (Add that to a Console.WriteLine)
It's a pretty common misconception that the async or await keywords create new threads. They don't.
The threads are created by running a Task. In this case, the thread is created by the Task.Delay call.
I need to create thread which will replace photo in Windows Forms window, than waits for ~1second and restore the previous photo.
I thought that the following code:
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
Thread.Sleep(1000);
pic.Image = Properties.Resources.PREV;
}, CancellationToken.None, TaskCreationOptions.LongRunning, ui)
do the job, but unfortunately doesn't. It freezes main UI thread.
That's because it's not guaranteed that there is one thread per one task. One thread can be used for processing several tasks.
Even TaskCreationOptions.LongRunning option can't help.
How I can fix it?
Thread.Sleep is a synchronous delay. If you want an asynchronous delay then use Task.Delay.
In C# 5, which is at present in beta release, you can simply say
await Task.Delay(whatever);
in an asynchronous method, and the method will automatically pick up where it left off.
If you are not using C# 5 then you can "manually" set whatever code you want to be the continuation of the delay yourself.
When you pass a new TaskScheduler that is from the current synchronization context, you actually telling the task to run on the UI thread. You actually want to do that, so you can update the UI component, however you don't want to sleep on that thread, since it will block.
This is a good example of when .ContinueWith is ideal:
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
},
CancellationToken.None,
TaskCreationOptions.None,
ui);
task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
.ContinueWith(t =>
{
pic.Image = Properties.Resources.Prev;
}, ui);
EDIT (Removed some stuff and added this):
What happens is that we're blocking the UI thread for only enough time to update pic.Image. By specifying the TaskScheduler, you're telling it what thread to run the task on. It's important to know that the relationship between Tasks and Threads is not 1:1. In fact, you can have 1000 tasks running on relatively few threads, 10 or less even, it all depends on the amount of work each task has. Do not assume each task you create will run on a separate thread. The CLR does a great job of balancing performance automatically for you.
Now, you don't have to use the default TaskScheduler, as you've seen. When you pass the UI TaskScheduler, that is TaskScheduler.FromCurrentSynchronizationContext(), it uses the UI thread instead of the thread pool, as TaskScheduler.Default does.
Keeping this in mind, let's review the code again:
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
},
CancellationToken.None,
TaskCreationOptions.None,
ui);
Here, we're creating and starting a task that will run on the UI thread, that will update the Image property of pic with your resource. While it does this, the UI will be unresponsive. Fortunately, this is a likely a very fast operation, and the user won't even notice.
task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
.ContinueWith(t =>
{
pic.Image = Properties.Resources.Prev;
}, ui);
With this code, we're calling the ContinueWith method. It does exactly what it sounds like. It returns a new Task object that will execute the lambda parameter when it runs. It will be started when the task has either completed, faulted or been cancelled. You can control when it will run by passing in TaskContinuationOptions. However, we're also passing a different task scheduler as we did before. This is the default task scheduler that will execute a task on a thread pool thread, thus, NOT blocking the UI. This task could run for hours and your UI will stay responsive (don't let it), because it's a separate thread from the UI thread that you are interacting with.
We've also called ContinueWith on the tasks we've set to run on the default task scheduler. This is the task that will update the image on the UI thread again, since we've passed that same UI task scheduler to the executing task. Once the threadpool task has finished, it will call this one on the UI thread, blocking it for a very short period of time while the image is updated.
You should be using a Timer to perform a UI task at some point in the future. Just set it to run once, and with a 1 second interval. Put the UI code in the tick event and then set it off.
If you really wanted to use tasks, you'd want to have the other task not run in the UI thread but rather in a background threat (i.e. just a regular StartNew task) and then use the Control.Invoke inside of the task to run a command on the UI thread. The problem here is that is' band-aid-ing the underlying problem of starting a task just to have it sleep. Better to just have the code not even execute in the first place for the full second.
I have a Backgroundworker whose purpose is to run jobs sequentially in the background. Now one job is implemented in multithreading way. That mean, the Backgroundworker will create several threads. I use Task Parallel Library so I use the Task.Factory.StartNew to create multiple Tasks.
After the tasks are run, the Backgroundworker waits all of them to finish.
Now I print the Backgroundworker's ManagedThreadID and all the tasks' ManagedThreadIDs. I found that the BackgroundWorker's ManagedThreadID is always the same as the first task's ManagedThreadID. I think this shouldn't happen so I cannot explain. I think the Backgroundworker's thread must be different to all the tasks it creates so the ManagedThreadIDs must be all different from each other.
Can anyone explain why this scenario happens? Thank you very much.
Edit:
The code is similar to this:
Backgroundworker.Run(){
// Print Thread.CurrentThread.ManagedThreadID.
var task = Task.Factory.StartNew(action1); // action1, action2 also print ManagedThredID.
taskList.Add(task);
task = Task.Factory.StartNew(action2);
taskList.Add(task);
... // Several other tasks.
foreach(var task in taskList) task.Wait();
}
You will find that one task has the same ManagedThreadID as the Backgroundworker.
I would go on a limb here and guess that the TPL is smart enough to reuse the BackgroundWorker thread. Since the worker waits for all tasks to complete running one task in the same thread is probably an optimization.
From further investigation, what you are seeing is a result of the expected behaviour of the Task.Wait method. You can read more at Task.Wait and "Inlining" on the Parallel Programming Team blog.
If the Task being Wait’d on has
already started execution, Wait has to
block. However, if it hasn’t started
executing, Wait may be able to pull
the target task out of the scheduler
to which it was queued and execute it
inline on the current thread.
The Background worker draws threads from the thread pool as well as TPL. What might happen is that the background worker is started, it draws a thread from the pool and fires TPL threads and returns immediately the thread to the pool. By the time TPL's first task is executed TPL draws a thread from the pool and it happens that it picks the same thread as the one once used by the background worker.
Of course that's just a supposition which cannot be verified because you haven't shown your code.
What you have stumbled upon is of course not a problem but a feature (optimization): The TPL is re-using threads as much as it can.
When you create a Task it is not immediately/permanently associated with a Thread. A Task is a Job that is put in a Queue and the Queue(s) are serviced by worker threads. So it could be that the Bgw Task is suspended and its thread returned to the pool, or more directly it could be done by the Wait():
// thread A
var t1 = Task.Startnew(...);
var t2 = Task.Startnew(...);
t1.Wait(); // Thread A is idle/available so Wait can execute t1
t2.Wait();
Use TaskCreationOptions.LongRunning to avoid re-cycling the background worker.