Reputation: 434
I have a simple code where I'm trying to get a better understanding of how a method can be called asynchronously in C#.
I have a function called Function1 which I want to run asynchronously
static void Function1(out int threadId)
{
Console.WriteLine("I'm inside Function 1. Going to sleep for 7 seconds...");
Thread.Sleep(7000);
Console.WriteLine("I'm awake now");
threadId = Thread.CurrentThread.ManagedThreadId;
}
Then I have a second function Function2 which I want to run normally (synchronously)
static void Function2()
{
Thread.Sleep(3000);
Console.WriteLine("I'm inside Function 2");
}
I also created a delegate with the same method signature as Function1
delegate void AsyncMethodCaller(out int threadId);
And here is my main calling method:
static void Main(string[] args)
{
int threadId;
AsyncMethodCaller caller = new AsyncMethodCaller(Function1);
caller.BeginInvoke(out threadId, null, null);
Function2();
}
In my main method, I expect Function1 to start running asynchronously; and then without waiting on it to finish, Function2 executes. So I expect the following output:
I'm inside the asynchronous Function 1. Going to sleep for 7 seconds...
I'm inside Function 2
I'm awake now
Instead I just get the following output:
I'm inside the asynchronous Function 1. Going to sleep for 7 seconds...
I'm inside Function 2
Why is my expectation different from reality? why is the "I'm awake now" line never reached?
Thank you
Upvotes: 3
Views: 2072
Reputation: 70701
The basic process lifetime rules for .NET are that a process exits when all foreground threads have exited. Any background threads are simply aborted; the process will not wait for them.
Furthermore, when you call a delegate's BeginInvoke()
method, this implicitly causes the delegate to be invoked using the thread pool. The thread pool is made entirely of background threads.
In other words, when you call BeginInvoke()
, you are telling .NET to invoke the delegate using a thread that does not in and of itself guarantee its own lifetime. That thread can (and in this case, is) aborted once the single main foreground thread of the process exits, which occurs immediately after you call Function2()
.
If you want the asynchronously invoked delegate to complete normally, you'll have to wait for it explicitly. E.g.:
IAsyncResult result = caller.BeginInvoke(out threadId, null, null);
Function2();
caller.EndInvoke(out threadId, result);
The EndInvoke()
method will block until the asynchronously invoked delegate has completed, allowing the main thread to wait for that to happen and thus ensuring that the thread used to invoke the delegate is not aborted before the invocation has completed.
The structure of your code example suggests you've already looked at MSDN's Calling Synchronous Methods Asynchronously, but in case you haven't I'll mention that page, as it includes a lot of details that would help explain how to deal with this particular scenario.
Upvotes: 4