65.9K
CodeProject 正在变化。 阅读更多。
Home

带代理的异步线程调用

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4投票s)

2012年3月23日

CPOL

3分钟阅读

viewsIcon

38749

downloadIcon

794

如何使用委托进行异步操作,它的优点和缺点。

介绍 

这是一个使用委托在 Windows 窗体上执行异步操作的小例子。由于本文主要关于使用异步线程调用,因此应用程序内部没有特别复杂的东西。但是,本文可能为异步操作提供一些有用的信息。所需代码的解释可以在项目本身中找到。

目的、优点和缺点

这实际上是一种不同的 - 并且可能是一种罕见的处理异步操作的方法。基本上,委托用于调用不同的非返回(void)函数。通过这样做,当您需要进行繁重的工作(例如大量计算、大规模 I/O 操作,甚至使用基于 Web 的应用程序(例如使用 Web 服务等))时,您可以在应用程序上获得更流畅、更少“滞后”的体验。

作为一个简单的例子,当从数据库调用大量数据时,可能需要一段时间才能加载并将您的数据呈现给用户。在这种情况下,用户可能会认为应用程序处于死锁状态,或者应用程序中存在故障。为了防止这些情况,用户需要了解后台实际发生的情况。通过使用这种方法,用户将能够在窗体上进行其他操作(如果可能),移动窗体本身、调整其大小以及可以做的其他任何事情。

但是,这种方法有一个主要的缺点,那就是 Control.CheckForIllegalCrossThreadCalls = false; 的部分。即使 Microsoft 允许开发人员绕过非法跨线程调用检查,但大多数开发人员认为使用它是糟糕的做法。但为什么这是一个糟糕的做法,它实际上做了什么?

在应用程序的运行时阶段,.NET Framework 检查是否以不安全的方式从另一个线程或多个线程访问和/或操作控件/对象。因此,基本上,只有在应用程序中存在多个线程时,此控制属性才会生效。该属性允许我们关闭运行时检查。这就是为什么大多数开发人员认为这是糟糕的做法,因为它无非是忽略了已经或将要发生的问题。正如我们大多数人会同意的那样,忽略问题不是解决问题的方法。

那么,这里的问题是什么?实际上没有一个问题。当多个线程(或用户)尝试同时访问和操作一个对象时,可能会发生各种各样的问题,这甚至更糟。所以基本上,主要问题是并发性。

您可以在下面的示例中看到非法跨线程调用的真正麻烦。

假设我们有一个名为 **result** 的变量,它的类型是 **integer**。以下代码将其值乘以 2 并将新值写入同一变量。因此,即使我们有多个线程,并且这些线程按顺序(同步)执行,我们也根本不会有任何问题。处理步骤如下所示。

result*=2;

但是,如果线程不是按顺序执行的,那么情况就大不相同了...

总而言之,使用 Control.CheckForIllegalCrossThreadCalls 完全取决于您和您的应用程序的结构。为了安全起见,请记住,此属性也可能导致严重的安全性问题。因此,最好在使用前三思而后行。

使用代码 

通常,整个事情都是通过委托和简单方法来实现的。委托用于发送调用消息。在此示例中,有两个主要方法。第一个是 DoStuff(),它显然是用于执行异步工作,第二个是 EndProcess(),它以 IAsyncResult 对象作为参数。在 DoStuff() 方法中,示例中没有给出任何复杂的内容。仅更改背景颜色并动态增加变量的值。

public void DoStuff()
{
    for (int i = 0; i...)
    {
         //...
    }
}

应用程序中没有使用额外的东西,如外部资源、图像等。源代码或演示应用程序可以轻松下载和运行。

© . All rights reserved.