C# 为什么对函数使用async/await比直接调用同一个函数花费更长的时间?

C# 为什么对函数使用async/await比直接调用同一个函数花费更长的时间?,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,我有一个需要在后台运行的函数,因为它会冻结UI直到完成。我尝试使用Async/Await,无论函数是否完成运行,它都允许我使用UI,但我注意到它要慢得多。为什么对函数使用async/await比直接调用同一个函数花费更长的时间?还有其他选择吗 private void btnClick(object sender, EventArgs e) { Math4OfficeRibbon.CallFunction(); MessageBox.Show("Task Finished"); }

我有一个需要在后台运行的函数,因为它会冻结UI直到完成。我尝试使用Async/Await,无论函数是否完成运行,它都允许我使用UI,但我注意到它要慢得多。为什么对函数使用async/await比直接调用同一个函数花费更长的时间?还有其他选择吗

private void btnClick(object sender, EventArgs e)
{
   Math4OfficeRibbon.CallFunction();
   MessageBox.Show("Task Finished");
}

public async void CallFunction()
{
   await Task.Run(() => AwaitedFunction());
}

public static void AwaitedFunction()
{
   // Do Something
   // Takes longer time this way
}

为了找出速度慢得多的原因,您可以在visual studio中使用
Console.WriteLine($“{event name}{DateTime.Now}”)
然后在输出窗口中查看花费时间最多的位置。
然而,关于替代方案,我建议您使用BackgroundWorker来运行您的任务。
请注意,您需要调用控件,以便通过backgroundWorker对ui进行更改

您还有RunWorkerCompleted事件,您可以使用它在任务运行完成后执行操作。
Backgroundworker还具有
IsBusy
属性,您可以将该属性与while循环一起使用,使线程等待其完成,而无需通过执行以下操作冻结UI:

While(_worker.IsBusy)
{
Application.DoEvents();
}
为了在ui线程上调用以执行操作,您需要在BackgroundWorker中执行以下操作:

BeginInvoke(new Action(()=> 
{
//ui action here for example:
MessageBox.show("test")
}));

但是,为了找出异步操作花费大量时间的原因,您必须使用控制台对其进行跟踪,因为您拥有所有的代码,并且您知道自己在做什么。

为了找出异步操作慢得多的原因,您可以使用
控制台.WriteLine($“{event name}{DateTime.Now}”)在visual studio中跟踪事件。
然后在输出窗口中查看花费时间最多的位置。
然而,关于替代方案,我建议您使用BackgroundWorker来运行您的任务。
请注意,您需要调用控件,以便通过backgroundWorker对ui进行更改

您还有RunWorkerCompleted事件,您可以使用它在任务运行完成后执行操作。
Backgroundworker还具有
IsBusy
属性,您可以将该属性与while循环一起使用,使线程等待其完成,而无需通过执行以下操作冻结UI:

While(_worker.IsBusy)
{
Application.DoEvents();
}
为了在ui线程上调用以执行操作,您需要在BackgroundWorker中执行以下操作:

BeginInvoke(new Action(()=> 
{
//ui action here for example:
MessageBox.show("test")
}));

但是,为了找出异步操作花费大量时间的原因,您必须使用控制台进行跟踪,因为您拥有所有代码,并且知道自己在做什么。

要慢得多吗?它可能会稍微慢一点,因为在引擎盖下它会产生状态机和其他东西,但我怀疑它会慢很多。。。该方法的调用速度较慢,还是其代码的运行速度较慢?@Stan它的速度要慢得多。。至少比正常函数调用慢20倍。@spender等待函数代码的运行时间比正常函数调用长。
TextRange
几乎肯定是绑定到UI线程的COM组件。对于大多数方法调用,您将进行大量编组以返回UI线程。从你在问题中选择的代码来看,所有这些都是不明显的。慢得多?它可能会稍微慢一点,因为在引擎盖下它会产生状态机和其他东西,但我怀疑它会慢很多。。。该方法的调用速度较慢,还是其代码的运行速度较慢?@Stan它的速度要慢得多。。至少比正常函数调用慢20倍。@spender等待函数代码的运行时间比正常函数调用长。
TextRange
几乎肯定是绑定到UI线程的COM组件。对于大多数方法调用,您将进行大量编组以返回UI线程。从您选择在问题中向我们展示的代码来看,所有这些都是不明显的。这是非常正确的,但MSDN强烈反对在新代码中使用
BackgroundWorker
:“在几乎所有情况下,基于异步的异步编程方法都比现有方法更可取。特别是,对于IO绑定的操作,这种方法比BackgroundWorker更好,因为代码更简单,并且您不必担心竞争条件。与Task.Run结合使用时,异步编程比BackgroundWorker更适合CPU绑定的操作,因为异步编程将运行代码的协调细节与Task.Run传输到线程池的工作分开“是的,尽管我只是试图指出OP要求的替代方案:)非常正确,但MSDN强烈反对在新代码中使用
BackgroundWorker
:“在几乎所有情况下,基于异步的异步编程方法都比现有方法更可取。特别是,对于IO绑定的操作,这种方法比BackgroundWorker更好,因为代码更简单,并且您不必担心竞争条件。与Task.Run结合使用时,异步编程比BackgroundWorker更适合CPU绑定的操作,因为异步编程将运行代码的协调细节与该任务的工作分开。Run传输到线程池“true,但我只是尝试按照OP的要求指出另一个选项:)