使用asynchronous任务来检查Excel中的数字的性能

我做了简单的validation方法,检查单元格中的数据是否是数字。

public async void checkNumberMethod(Excel.Range numericRange, bool isCompulsary) { int errorCnt = await checkNumberAsync( numericRange, colTable, isCompulsary); } private Task<int> checkNumberAsync(Excel.Range numericRange, bool isCompulsary) { return Task.Run<int>(() => checkNumber(numericRange,isCompulsary)); } private int checkNumber(Excel.Range numericRange, bool isCompulsary) { if (isCompulsary == true) { foreach(Excel.Range item in numericRange) { //Do stuff } } else { foreach(Excel.Range item in numericRange) { //Do stuff } } } 

并且调用这个方法,

 checkNumberMethod(numericRange, true); checkNumberMethod(numericRange, false); 

但是这比呼叫慢得多

 checkNumber( numericRange, true); checkNumber( numericRange, false); 

任务并不总是更快?
如果你给我任何想法,我将非常感激。

是的, Task并不总是比直接调用方法快。 让我们深入您的代码,看看这里发生了什么:

您正在调用checkNumberMethod并在.NET创build和机器状态之后asynchronous启动内部方法,这将在任务完成后加载。 里面还有一个Task ,它占用线程池中后台运行的资源。

所以, async/await降低你的程序的速度,如果你的工作很短 – 状态机创build和任务后台运行的开销是一个恒定的值,这将永远在你的程序中,即使是即时方法。

不,任务不会更快。 它与性能没有任何关系,只是意味着它并行运行。 如果你正在等待它完成,你没有从平行度中获得任何东西,但是开销。

这是我不喜欢COM为你穿线的一个主要原因。 在这种情况下, Excel.Range是一个STA COM组件,它将自动执行线程编组以尝试“帮助”。

每当您尝试从另一个上下文中使用它们时,STA组件将同步回到它们自己的线程。 因此,在这种情况下,您的代码正在将一些工作发送到后台线程,然后该后台工作不断转向并同步到背后的UI线程。

你可以把STA的东西从“真正的工作”中分离出来,例如,在调用Task.Run之前,把你需要的Range数据拷贝到一个常规的List<T> 。 但是,您仍然必须考虑其他答案中提到的问题,即如果您只有less量工作,将其推送到后台线程只会增加开销。

最后要注意的是,“asynchronous”并不意味着“更快”。 asynchronous只是在不使用多个线程的情况下完成多个任务的一种方式。

正如其他人指出的那样,使用Task不一定更快,但是在客户端,它可以让您将工作推到后台,并保持客户端的响应。 使用TPL,您还可以并行处理结果,速度更快。 例如

 numericRange.AsParallel().ForAll(() => /* check each number*/); 

PLINQ的AsParallelParallel.ForEach允许你Parallel.ForEach处理你的数据。 这里有一些关于这个主题的博客。

在调用asynchronousIO操作时, Tasks更好,因为它们允许您释放当前线程以执行其他工作。