C# 异步调用同步方法

C# 异步调用同步方法,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,我有一个简单的代码,试图更好地理解如何在C#中异步调用方法 我有一个名为Function1的函数,我想异步运行它 static void Function2() { Thread.Sleep(3000); Console.WriteLine("I'm inside Function 2"); } 然后我有第二个函数Function2,我想正常运行(同步运行) 我还创建了一个与Function1具有相同方法签名的委托 delegate void AsyncMethodCaller

我有一个简单的代码,试图更好地理解如何在C#中异步调用方法

我有一个名为Function1的函数,我想异步运行它

static void Function2()
{
    Thread.Sleep(3000);
    Console.WriteLine("I'm inside Function 2");
}
然后我有第二个函数Function2,我想正常运行(同步运行)

我还创建了一个与Function1具有相同方法签名的委托

delegate void AsyncMethodCaller(out int threadId);
下面是我的主要调用方法:

static void Main(string[] args)
{
    int threadId;
    AsyncMethodCaller caller = new AsyncMethodCaller(Function1);
    caller.BeginInvoke(out threadId, null, null);
    Function2();
}
在我的main方法中,我希望Function1开始异步运行;然后在不等待它完成的情况下执行Function2。因此,我期望得到以下结果:

我在异步函数1中。要睡7天吗 秒
我在函数2中
我现在醒了

相反,我只得到以下输出:

我在异步函数1中。要睡7天吗 秒
我在函数2中

为什么我的期望与现实不同?为什么“我现在醒了”这句话永远也达不到


谢谢

对于.NET来说,基本的进程生存期规则是,当所有前台线程都退出时,进程就会退出。任何后台线程都被简单地中止;这个过程不会等待他们

此外,当调用委托的
BeginInvoke()
方法时,这会隐式地导致使用线程池调用委托。线程池完全由后台线程组成

换句话说,当您调用
BeginInvoke()
时,您告诉.NET使用一个线程来调用委托,该线程本身并不保证其自身的生存期。在调用
Function2()
后,一旦进程的单个主前台线程退出,该线程就会中止(在本例中,该线程也会中止)

如果希望异步调用的委托正常完成,则必须显式地等待它。例如:

IAsyncResult result = caller.BeginInvoke(out threadId, null, null);

Function2();

caller.EndInvoke(out threadId, result);
EndInvoke()
方法将阻塞,直到异步调用的委托完成,从而允许主线程等待该事件发生,从而确保用于调用委托的线程不会在调用完成之前中止


代码示例的结构表明您已经看过MSDN,但如果您没有看过,我将提到该页面,因为它包含了很多详细信息,有助于解释如何处理此特定场景。

因为退出Main之前不需要等待Function1完成,所以每次我想异步调用一个方法时,我是否必须创建一个委托?有没有一种方法可以在不使用“BeginInvoke()”方法的情况下异步调用Function1?当然。事实上,使用
BeginInvoke()
可能是异步执行方法最不常见的方式。今天更典型的做法是将调用封装在
任务中。例如,
Task Task=Task.Run(()=>Function1(out-threadId));函数2();task.Wait()
将等同于上述内容,但改用
任务
。请注意,这样做,您不需要声明自定义的
asynchmethodcaller
委托类型,因为该方法由匿名方法直接调用,而不是委托实例的目标。
IAsyncResult result = caller.BeginInvoke(out threadId, null, null);

Function2();

caller.EndInvoke(out threadId, result);