技术开发 频道

在.NET多线程程序中使用异步调用的简易方法

  【IT168 技术】对于开发者来说,运行异步任务简直就是一场恶梦,特别是初学者更是如此。在本文附带的代码中,您将发现一个简单的AsyncWorker类,它能够使您轻松完成异步任务的处理,即使您对异步调用没有全面深入的了解。当然,我们也很希望看到您贡献的代码,尤其是对于ReportProgress函数,因为它还未经测试。

  背景知识

  我为什么编写这个助手类(helper class)呢? 简单地说,这是因为我不喜欢.NET BackgroundWorker类,以及所有与IsBusy参数有关的问题。有时候,即使您成功地终止了异步任务,IsBusy也不会从true变为false。类backgroundWorker会强迫您在while循环中使用Application.DoEvents。也许还有其它正确使用它的方法,但是我至今还没找到。我尝试按照backgroundWorker的设计方法建立一个尽可能简单的替换物。

  代码用法

  如果您看过BackgroundWorker的文档,那么使用下面的代码也应该不成问题。为了初始化AsyncWorker,我们做如下定义:

  AsyncCallback m_asyncWorker;

  然后,在您的代码(构造函数)中对其进行初始化,如下所示:

//通过设置maximumCount,我们可以对简单的ThreadPool进行摹拟。  
//参数maximumCount用于指出可以同时启动多少个并行的线程。如果abortIfBusyParameter被设为true,那么其他线程就只能等待,或者被拒绝。  
this.m_asyncWorker = new AsyncWorker(1);  
//分配一个后台任务  
this.m_asyncWorker.DoWork += new DoWorkEventHandler(m_asyncWorker_DoWork);

  您的后台任务可以是任何您喜欢的东西:

void m_asyncWorker_DoWork(object sender, DoWorkEventArgs e)
    {             
        Console.WriteLine(
"Hello world! I was started asynchronously.");          
    }  

  最后调用background worker :

//因为abortIfBusyParameter 被设置为true,所以如果前面的调用仍然在运行的话,RunWorkerAsync将返回false(中止调用)。  
if (!this.m_asyncWorker.RunWorkerAsync(true)) {  
    Console.WriteLine(
"Worker in use....");  
}

  通过把RunWorkerAsync参数abortIfBusy设置为true,即使前面的异步调用仍在运行,您也可以跳过这个事件。通过将其设为false,它会进入一个等待队列,并在IsBusy从true转换为false的时候马上触发。 这个机制对于性能敏感的应用程序来说非常有用。如果您有许多启动异步调用的“低优先级”事件,并且如果前面的异步调用仍在运行(IsBusy),那么您可以决定是否应该启动另一个异步调用。

  例如:如果您在屏幕上拖动一个对象的时候,那么就无需每次都重绘它。只有当IsBusy为false的时候才需对其进行绘制。 如果您想要获得平滑效果,只需增加maximumCount(您的线程池)即可。

  最后,如果您需要一个回调函数,那么您可以自己预订RunWorkerCompleted事件。

//分配RunWorkerCompleted。它是您的回调函数事件。  

this.m_asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler

  结束语

  希望这个工具可以使您的生活变得更加轻松。请不要询问JustDoSomething类的锁定问题,因为它是其它测试的一部分。

0
相关文章