let's say we have some simple code like this :
private static void Main()
{
Console.WriteLine("Main thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Action asyncCaller1 = () => LongPerfomingTask(5);
Action asyncCaller2 = () => LongPerfomingTask(3);
var asyncResult1 = asyncCaller1.BeginInvoke(null, null);
var asyncResult2 = asyncCaller2.BeginInvoke(null, null);
asyncResult1.AsyncWaitHandle.WaitOne();
asyncResult2.AsyncWaitHandle.WaitOne();
Console.WriteLine("Done");
}
private static void LongPerfomringTask(int seconds)
{
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("Thread {0} finished execution", Thread.CurrentThread.ManagedThreadId);
}
Delegate.BeginInvoke() does not create a thread, It's executing code in a caller's thread when it is in idle state, right?So, why the output of this sample application is like this :
Main thread 1
Thread 4 finished execution
Thread 3 finished execution
Done
No, Delegate.BeginInvoke uses the thread pool. Always. There's no concept of "executing in the caller's thread when it's idle" unless you're thinking of adding tasks to a UI message queue... were you getting confused with Control.BeginInvoke / Dispatcher.BeginInvoke?
In this case you've got a console app - there's no message pumping going on to start with.
#taras.roshko: Here's a resource to boost your understanding of ThreadPool:
Chapter on Threading
Related
I have an app (http web load test app) that need new Thread() , and the HttpClient only have async method, so how do I run the action synchronous
ps: I tried use full Task but the thread number it use is low (30 thread only),
so I want to try the Thread to see if it can be much faster.
Will the .GetAwaiter().GetResult() cost 2 thread (100 thread became 200 thread) ?
previous I use
for(var i = 0; i< 200;i++)
{
Task.Run(async ()=>
{
while(thereStillHaveRequestToMake)
{
await httpclient.SendAsync() // some thing like this
}
});
}
// the prolem is there are only 30-40 Thread in use (From TaskManager)
So I want to switch to use Thread directly
for(var i = 0; i< 200;i++)
{
new Thread(()=>
{
while(thereStillHaveRequestToMake)
{
httpclient.SendAsync().GetAwaiter.GetResult()
}
});
}
I have an app (http web load test app) that need new Thread()
Why?
HttpClient only have async method, so how do I run the action synchronously
Why.
Or How to call asynchronous method from synchronous method in C#?.
I tried use full Task but the thread number it use is low (30 thread only),
A task is not a thread. We can easily test this by running methods on the thread pool. First we set the ThreadPool to only allow a single thread.
class Program
{
private const int MaxThreads = 1;
static void Main(string[] args)
{
ThreadPool.SetMinThreads(MaxThreads, 1);
Console.WriteLine(ThreadPool.SetMaxThreads(MaxThreads, 1));
Task.Run(() => SomeMethod(new StateInfo { Order = 0, WaitFor = 3000 }));
Task.Run(() => SomeMethod(new StateInfo { Order = 1, WaitFor = 3000 }));
Task.Run(() => SomeMethod(new StateInfo { Order = 2, WaitFor = 3000 }));
Console.WriteLine("Main thread does some work, then sleeps.");
Thread.Sleep(5000);
Console.WriteLine("Main thread exits.");
}
static void SomeMethod(Object stateInfo)
{
var si = (StateInfo)stateInfo;
Console.WriteLine($"Hello from the thread pool. {si.Order}");
Thread.Sleep(si.WaitFor);
}
public class StateInfo
{
public int Order { get; set; }
public int WaitFor { get; set; }
}
}
Output
True
Main thread does some work, then sleeps.
Hello from the thread pool. 1
Hello from the thread pool. 2
Main thread exits.
Since we have 1 thread and we've told the first two methods to wait a total of 6 seconds, but the main thread exits after 5 seconds, we never get a message from the 3rd method. We can easily test this by changing MaxThreads = 2 which yields something like the following (we get 3 results, but not necessarily in order):
True
Main thread does some work, then sleeps.
Hello from the thread pool. 1
Hello from the thread pool. 2
Hello from the thread pool. 3
Main thread exits.
Now that we've guaranteed we're using a single thread, lets see how many requests we can do simultaneously synchronously.
static void SomeMethod(Object stateInfo)
{
var si = (StateInfo)stateInfo;
Console.WriteLine($"Hello from the thread pool. {si.Order}");
httpClient.GetStringAsync($"https://www.google.com");
Console.WriteLine($"Hello from the thread pool. {si.Order} finished");
}
Since we aren't async/await the request, it runs synchronously so the output is predictably:
True
Main thread does some work, then sleeps.
Hello from the thread pool. 1
Hello from the thread pool. 1 finished
Hello from the thread pool. 2
Hello from the thread pool. 2 finished
Hello from the thread pool. 3
Hello from the thread pool. 3 finished
Main thread exits.
That doesn't really load test anything because synchronous calls wait until the previous one finishes. In order to load test we want many concurrent calls. This is easily done with a single thread using async await.
Update the method:
static async Task SomeMethod(Object stateInfo)
{
var si = (StateInfo)stateInfo;
Console.WriteLine($"Hello from the thread pool. {si.Order}");
await httpClient.GetStringAsync($"https://www.google.com");
Console.WriteLine($"Hello from the thread pool. {si.Order} finished");
}
Use linq to make a list of requests, and wait for all of them to finish.
static void Main(string[] args)
{
ThreadPool.SetMinThreads(MaxThreads, 1);
Console.WriteLine(ThreadPool.SetMaxThreads(MaxThreads, 1));
Console.WriteLine("Start Requests");
var requests = Enumerable.Range(0, 200)
.Select(async (x) => await Task.Run(() => SomeMethod2(new StateInfo { Order = x, WaitFor = 0 })))
.ToArray();
Console.WriteLine("Wait for them.");
Task.WaitAll(requests.ToArray());
Console.WriteLine("Main thread exits.");
Console.ReadKey();
}
Yields (I didn't want to put 400 lines of code here)
True
Start Requests
Wait for them.
Hello from the thread pool. 0
Hello from the thread pool. 1
Hello from the thread pool. 2
.... repeating to
Hello from the thread pool. 199
Hello from the thread pool. 178 finished
Hello from the thread pool. 5 finished
Hello from the thread pool. 3 finished
Hello from the thread pool. 15 finished
Hello from the thread pool. 26 finished
Hello from the thread pool. 4 finished
.... repeating until all 200 requests are finished
Main thread exits.
200 Http Requests on a single thread. Why do you need more threads?
How can I check if a thread returned to the thread pool, using VS C# 2015 debugger?
What's problematic in my case is the fact that it cannot be detected by debugging line by line.
async Task foo()
{
int y = 0;
await Task.Delay(5);
// (1) thread 2000 returns to thread pool here...
while (y<5) y++;
}
async Task testAsync()
{
Task task = foo();
// (2) ... and here thread 2000 is back from the thread pool, to run the code below. I want
// to confirm that it was in the thread pool in the meantime, using debugger.
int i = 0;
while (i < 100)
{
Console.WriteLine("Async 1 before: " + i++);
}
await task;
}
In the first line of testAsync running on thread 2000, foo is called. Once it encounters await Task.Delay(5), thread 2000 returns to thread pool (allegedly, I'm trying to confirm this), and the method waits for Task.Delay(5) to complete. In the meantime, the control returns to the caller and the first loop of testAsync is executed on thread 2000 as well.
So between two consecutive lines of code, the thread returned to thread pool and came back from there. How can I confirm this with debugger? Possibly with Threads debugger window?
To clarify a bit more what I'm asking: foo is running on thread 2000. There are two possible scenarios:
When it hits await Task.Delay(5), thread 2000 returns to the thread pool for a very short time, and the control returns to the caller, at line (2), which will execute on thread 2000 taken from the thread pool. If this is true, you can't detect it easily, because Thread 2000 was in the thread pool during time between two consecutive lines of code.
When it hits await Task.Delay(5), thread 2000 doesn't return to thread pool, but immediately executes code in testAsync starting from line (2)
I'd like to verify which one is really happening.
There is a major mistake in your assumption:
When it hits await Task.Delay(5), thread 2000 returns to the thread pool
Since you don't await foo() yet, when thread 2000 hits Task.Delay(5) it just creates a new Task and returns to testAsync() (to int i = 0;). It moves on to the while block, and only then you await task. At this point, if task is not completed yet, and assuming the rest of the code is awaited, thread 2000 will return to the thread pool. Otherwise, if task is already completed, it will synchronously continue from foo() (at while (y<5) y++;).
EDIT:
what if the main method called testAsync?
When synchronous method calls and waits async method, it must block the thread if the async method returns uncompleted Task:
void Main()
{
var task = foo();
task.Wait(); //Will block the thread if foo() is not completed.
}
Note that in the above case the thread is not returning to the thread pool - it is completely suspended by the OS.
Maybe you can give an example of how to call testAsync so that thread 2000 returns to the thread pool?
Assuming thread 2k is the main thread, it cannot return to the thread pool. But you can use Task.Run(()=> foo()) to run foo() on the thread pool, and since the calling thread is the main thread, another thread pool thread will pick up that Task. So the following code:
static void Main(string[] args)
{
Console.WriteLine("main started on thread {0}", Thread.CurrentThread.ManagedThreadId);
var testAsyncTask = Task.Run(() => testAsync());
testAsyncTask.Wait();
}
static async Task testAsync()
{
Console.WriteLine("testAsync started on thread {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Console.WriteLine("testAsync continued on thread {0}", Thread.CurrentThread.ManagedThreadId);
}
Produced (on my PC) the following output:
main started on thread 1
testAsync started on thread 3
testAsync continued on thread 4
Press any key to continue . . .
Threads 3 and 4 came from and returned to the thread pool.
You can print out the Thread.CurrentThread.ManagedThreadId to the console. Note that the thread-pool is free to re-use that same thread to run continuations on it, so there's no guarantee that it'll be different:
void Main()
{
TestAsync().Wait();
}
public async Task FooAsync()
{
int y = 0;
await Task.Delay(5);
Console.WriteLine($"After awaiting in FooAsync:
{Thread.CurrentThread.ManagedThreadId }");
while (y < 5) y++;
}
public async Task TestAsync()
{
Console.WriteLine($"Before awaiting in TestAsync:
{Thread.CurrentThread.ManagedThreadId }");
Task task = foo();
int i = 0;
while (i < 100)
{
var x = i++;
}
await task;
Console.WriteLine($"After awaiting in TestAsync:
{Thread.CurrentThread.ManagedThreadId }");
}
Another thing you can check is ThreadPool.GetAvailableThreads to determine if another worker has been handed out for use:
async Task FooAsync()
{
int y = 0;
await Task.Delay(5);
Console.WriteLine("Thread-Pool threads after first await:");
int avaliableWorkers;
int avaliableIo;
ThreadPool.GetAvailableThreads(out avaliableWorkers, out avaliableIo);
Console.WriteLine($"Available Workers: { avaliableWorkers},
Available IO: { avaliableIo }");
while (y < 1000000000) y++;
}
async Task TestAsync()
{
int avaliableWorkers;
int avaliableIo;
ThreadPool.GetAvailableThreads(out avaliableWorkers, out avaliableIo);
Console.WriteLine("Thread-Pool threads before first await:");
Console.WriteLine($"Available Workers: { avaliableWorkers},
Available IO: { avaliableIo }");
Console.WriteLine("-------------------------------------------------------------");
Task task = FooAsync();
int i = 0;
while (i < 100)
{
var x = i++;
}
await task;
}
On my machine, this yields:
Thread-Pool threads before first await:
Available Workers: 1023, Available IO: 1000
----------------------------------------------
Thread-Pool threads after first await:
Available Workers: 1022, Available IO: 1000
I'd like to verify which one is really happening.
There is no way to "verify" that with debugger, because the debugger is made to simulate the logical (synchronous) flow - see Walkthrough: Using the Debugger with Async Methods.
In order to understand what is happening (FYI it's your case (2)), you need to learn how await works starting from Asynchronous Programming with Async and Await - What Happens in an Async Method section, Control Flow in Async Programs and many other sources.
Look at this snippet:
static void Main(string[] args)
{
Task.Run(() =>
{
// Initial thread pool thread
var t = testAsync();
t.Wait();
});
Console.ReadLine();
}
If we make the lambda to be async and use await t; instead of t.Wait();, this is the point where the initial thread will be returned to the thread pool. As I mentioned above, you cannot verify that with debugger. But look at the above code and think logically - we are blocking the initial thread, so if it' wasn't free, your testAsync and foo methods will not be able to resume. But they do, and this can easily be verified by putting breakpoint after await lines.
I am playing with the async/await in the C# and while I think that I understand most of the concepts, I can not explain why the code line "var rxres = await ..." first time runs on my UDP thread, and after further receptions of the packets runs on the worker thread. As far as I understand, I am not "yielding" back to the thread function and it is still alive and so all invocations of ReceiveAsync should run on the thread I created.
static void Main(string[] args)
{
var ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
var udpThread = new Thread(async () =>
{
ListenUdpAsync().Wait();
});
udpThread.Name = "UDP THREAD";
udpThread.Start();
ewh.WaitOne();
}
static public async Task ListenUdpAsync()
{
var localPort = 5555;
var localBind = new IPEndPoint(IPAddress.Any, localPort);
using (var udpc = new UdpClient(localBind))
{
while(true)
{
var rxres = await udpc.ReceiveAsync();
Console.WriteLine("Rx From: " + rxres.RemoteEndPoint);
Console.WriteLine("Rx Data: " + Encoding.ASCII.GetString(rxres.Buffer));
}
}
}
I am not "yielding" back to the thread function
The method yields once hitting await udpc.ReceiveAsync(), that is how async-await works. ListenAsync itself synchronously blocks, but since there is no sync context that comes into play, the continuation is able to marshal itself onto an arbitrary thread pool thread.
so all invocations of ReceiveAsync should run on the thread I created.
Not really. Generally, when you're running inside a console application, it uses the default TaskScheduler, which internally uses the thread pool to execute continuations on an arbitrary threadpool thread. Ones ReceiveAsync() completes, its continuation needs to be scheduled somewhere, and that place is on the thread pool.
On a side note - there is no reason to use the async modifier on the delegate, as you're not awaiting anything inside, but synchronously blocking.
I have a long running method and I want to add timeout into it. Is it feasible to do that? Something like:
AbortWaitSeconds(20)
{
this.LongRunningMethod();
}
Where when it reached 20 seconds, the method will be aborted. The method doesn't have loop and I do not have a control/code over that method.
try this
class Program
{
static void Main(string[] args)
{
if (RunWithTimeout(LongRunningOperation, TimeSpan.FromMilliseconds(3000)))
{
Console.WriteLine("Worker thread finished.");
}
else
{
Console.WriteLine("Worker thread was aborted.");
}
}
static bool RunWithTimeout(ThreadStart threadStart, TimeSpan timeout)
{
Thread workerThread = new Thread(threadStart);
workerThread.Start();
bool finished = workerThread.Join(timeout);
if (!finished)
workerThread.Abort();
return finished;
}
static void LongRunningOperation()
{
Thread.Sleep(5000);
}
}
you can see it
See my answer to this question for a generic solution.
Do the calculation in a background thread and wait until the thread finishes. To abort calculation, use Thread.Abort(), this will throw a ThreadAbortException in the calculation thread.
You can only abort long running process from the same thread if you have a code point in which to introduce a check and exit. This is because - clearly - the thread is busy, so it can't process checks to abort itself. So, your example which only contains one call to 'LongRunningMethod' could not be aborted from the same thread. You'd need to show more code in order to get direction on that.
As a general rule, long-running tasks are best sent to different threads (e.g; via a BackgroundWorker or new Thread) so they can be aborted.
Here is a simple way to do this;
private void StartThread()
{
Thread t = new Thread(LongRunningMethod);
t.Start();
if (!t.Join(10000)) // give the operation 10s to complete
{
// the thread did not complete on its own, so we will abort it now
t.Abort();
}
}
private void LongRunningMethod()
{
// do something that'll take awhile
}
Since you have no control over that code I believe the correct approach would be to run that code using WaitHandles and the ThreadPool:
WaitHandle waitHandle = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(<long running task delegate>), waitHandle);
WaitHandle.WaitAll(new[]{ waitHandle }, <timeout>);
Here you can find more info on how WaitHandle works.
I'm running a number of time\CPU intensive processes (TimeExpensive type) one after another. The Main thread (A) starts TimeExpensive process in another thread (B) asynchronously and becomes inactive. On Completion, Thread B fires caller's completion handler synchronously and starts next TimeExpensive process in thread B. A new thread (C) is created but After starting C, B finishes. So for n processes, n threads are created and most of time, they don't co-exist.
One may wish its implementation in linear single threaded way, but TimeExpensive is implemented by third party and while it runs, it uses all system cores and runs for hours.
//This will run as console app
class Program
{
static void Main(string[] args)
{
new Program().StartJobs();
}
void StartJobs()
{
Main mainJob = new Main();
mainJob.MainCompletionEvent +=
new Action<object, EventArgs>(mainJob_MainCompletionEvent);
mainJob.Start();
}
void mainJob_MainCompletionEvent(object sender, EventArgs e)
{
//if(success) Environment.Exit(0);
}
}
class Main
{
int processCounter = 0;
public event Action<object, EventArgs> MainCompletionEvent;
public void Start()
{
//...do other important tasks here...
processCounter++;
TimeExpensive te = new TimeExpensive();
te.CompletionEvent += new Action(TimeExpensive_CompletionHandler);
Thread aThread = new Thread(te.Run);
aThread.IsBackground = false;
aThread.Name = "TimeExpensive Thread: " + processCounter;
aThread.Start();
}
void TimeExpensive_CompletionHandler()
{
Console.WriteLine("current Thread Name: " + Thread.CurrentThread.Name);
//Start another Process In Background if
if (processCounter < 5)
{
Start();
}
else
{
Console.ReadKey();
if (JobCompletionEvent != null)
JobCompletionEvent(this, new EventArgs());
}
}
}
class TimeExpensive
{
public event Action CompletionEvent;
public void Run()
{
//doing time expensive task
//...
//when finish Notify completion Handler...
if (CompletionEvent != null)
{
CompletionEvent();
}
}
}
//Output
current Thread Name: TimeExpensive Thread: 1
current Thread Name: TimeExpensive Thread: 2
current Thread Name: TimeExpensive Thread: 3
current Thread Name: TimeExpensive Thread: 4
current Thread Name: TimeExpensive Thread: 5
Above implementation mimics the behavior I described. The thing that is bugging me is the Event Handler running synchronously until the next thread starts and during this time, it's doing lots of tasks that it's not designed for.
Not sure if this is good, Is there a way I can go back to thread A while in Thread B's completion handler? or Should I better start event handler execution using another delegate.BeginInvoke?
I wish doing it with simple yet safe approach. Any help is greatly appreciated.
P.S I read lots of posts but no one was dealing well with this scenario.
Edit
Static main is added to show how to kick start this code in console app. Remember one can also create UI to start "Main" job. It'll definitely create BackgroundWorker thread to create mainJob object and run it.
Thanks!
Is there a way I can go back to thread A while in Thread B's completion handler?
No, you don't have the plumbing in place to marshal a call from one thread to another. That kind of plumbing is provided by the main thread of a GUI app. Out of necessity, user interfaces are pretty fundamentally thread-unsafe. There are several implementation details of a UI thread that support such marshaling. It acts like a consumer in a typical implementation of a producer/consumer threading model.
Which requires a thread-safe queue and a loop in the consumer that reads the queue. You may recognize this as the message queue in a Windows GUI app. With the message loop that calls GetMessage to read notifications and act on them. Marshaling a call is now simple, you just post a message to the message queue, the UI thread reads it and executes the request. Posting is implemented by Control.BeginInvoke for Winforms and Dispatcher.BeginInvoke for WPF.
You certainly can implement this synchronization mechanism yourself. The .NET 4 BlockingCollection class makes it easy. But do keep in mind that you have to fundamentally alter the way thread A executes. Staying responsive to requests posted to the queue is important. The kind of problem that a class like BackgroundWorker tries to solve. Keep in mind that the GUI message loop exists because it is necessary, UI isn't thread-safe. A console app doesn't (typically) have the same kind of burden, the console is thread-safe.
The problem you are experiencing is due to how hard it is to do threading correctly. I coded your example with actors:
type Actor<'a> = MailboxProcessor<'a>
type SupMsg = WaitForDone of AsyncReplyChannel<string>
type ProgramState = RunNumber of int * Actor<WorkerMsg> option
and WorkerMsg = Begin of Id * AsyncReplyChannel<string>
and Id = int
let startComputation () = Actor.Start(fun inbox ->
async {
let! Begin(id, chan) = inbox.Receive()
printfn "Running Computation"
do! Async.Sleep(20) // zZz
chan.Reply(sprintf "'%i is done!'" id) })
let sup () = Actor.Start(fun inbox ->
let rec loop state =
async {
match state with
| RunNumber(_, None) -> return! loop <| RunNumber(1, Some(startComputation ()))
| RunNumber(run, Some(active)) ->
let! completed = active.PostAndAsyncReply(fun chan -> Begin(run, chan))
printfn "sup observed: %s" completed
let active' = Some(startComputation ())
if run <> 5 then return! loop <| RunNumber(run + 1, active')
else return! isDone () }
and isDone () =
async {
let! WaitForDone(chan) = inbox.Receive()
return chan.Reply("all done") }
loop <| RunNumber(0, None))
[<EntryPoint>]
let main args =
printfn "%s" <| (sup ()).PostAndReply(fun chan -> WaitForDone(chan))
0
Which as output:
> main();;
Running Computation
sup observed: '1 is done!'
Running Computation
sup observed: '2 is done!'
Running Computation
sup observed: '3 is done!'
Running Computation
sup observed: '4 is done!'
Running Computation
sup observed: '5 is done!'
all done
val it : int = 0
As you can see, it becomes a breeze to communicate across threads. If you library is a third-party library, then it is easy to replace Async.Sleep(20) with the invocation to the library.