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

异步编程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (8投票s)

2013年11月11日

CPOL

3分钟阅读

viewsIcon

24946

downloadIcon

566

使用任务并行库的异步编程。

引言

.Net Framework 4.0 引入了任务并行库 (TPL)。 该库通过两种重要方式增强了多线程编程。 首先,它简化了多个线程的创建和使用。 其次,它自动利用多个处理器。 换句话说,通过使用 TPL,您可以使应用程序自动缩放以利用可用处理器的数量。 通过使用 Task 对象,您可以简化代码并利用以下有用功能

  • 在任务启动后的任何时间注册回调,其形式为任务延续。
  • 通过使用 ContinueWith() 方法,协调响应于 Begin_ 方法执行的多个操作。
  • 将异步 I/O 绑定和计算绑定操作封装在同一个 Task 对象中。
  • 监视 Task 对象的状态。

背景

在这里,我给出了一些技巧,说明如何访问在 TPL 中异步运行的工作进程。 任务调用、任务暂停操作、任务取消。 TPL 的核心是 Task 类。 对于 TPL,执行的基本单元是由 Task 封装的,而不是 Thread。 Task 与 Thread 的不同之处在于 Task 是表示异步操作的抽象。 Thread 封装了一个执行线程。 Task 类(以及所有 TPL)在 System.Threading.Tasks 中定义。

创建任务

为异步操作创建 Task。 首先,我们必须实现名为 System.Threading.Tasks 的命名空间才能使用 TPL。 首先,为 Task CancellationTokenSource 创建一个对象,如 null_ 在方法外部,并在方法内部实例化 Task 对象和 CancellationToken 对象。

Task tsk = null;
CancellationTokenSource cnslTokSrc = null;   

Task 对象被启动以启动异步进程,而 cancellationTokenSource 对象被分配给 CancellationToken 对象。 Task.Factory.StartNew() 方法通过调用 TaskFactory 定义的 StartNew( ) 方法,一步创建任务并开始执行。 TaskFactory 是一个类,它提供了各种方法来简化任务的创建和管理。 默认的 TaskFactory 可以从 Task 提供的只读 Factory 属性中获得。 使用此属性,您可以调用任何 TaskFactory 方法。 StartNew( ) 自动为操作创建一个 Task 实例,然后通过将其调度为执行来启动该任务。 因此,无需调用 Start( ) 来调用操作 Task。

void LoadSrc()
{
	cnslTokSrc = new CancellationTokenSource();     //  Instantiating the cancellationTokenSource.
	//  Assign cancellationTokenSource object token to CancellationToken object.
    CancellationToken ct = cnslTokSrc.Token;
    //  Parameterized Action delegate using Lambda Expression with anonymous method.
    // The Object State is passed to the action delegate parameter and set to the method(typeCasted) to be invoked.
    tsk = Task.Factory.StartNew((str) => { Load((List<string>)str); }, Lst, ct);
    tsk.ContinueWith((s) =>
    //  It is the callBack method Invoked when the task completed.
    {
    	if (!ct.IsCancellationRequested)
    	//  If the cancellationTokenSource is set to be canceled the IsCancellationRequest
    	// is set to be True. The Only thing is to identify that the task
    	// is completed with Cancellation Or Successfull.
        {
            MessageBox.Show("Operation Completed Successfully...!", 
              "Information", MessageBoxButton.OK, MessageBoxImage.Information);
        }
        else
        {
            if (MessageBox.Show("Operation Cancelled...!", 
                "Information", MessageBoxButton.OK, 
                MessageBoxImage.Information) == MessageBoxResult.OK)
            {
                cnslTokSrc.Dispose();       //  Disposing the CancellationTokenSource for next Initiation.
                IsCanceled = false;
            }
        }
        IsBusy = false;
        tsk.Dispose();
    });
}

任务延续 

TPL 具有名为 ContinuWith() 方法的特性。 此方法充当 callBack 方法,使您可以在任何时候或在 Task 完成后调用任何要调用的方法。

tsk.ContinueWith((s) =>{}); 

任务取消 

CancellationToken 类支持通过使用取消令牌进行取消。 对象通过使用 CancellationTokenSource 创建取消令牌,然后将取消令牌传递给任何数量的应收到取消通知的线程或对象。 该令牌不能用于启动取消。 当拥有对象在 CancellationTokenSource 上调用 Cancel 时,每个取消令牌副本上的 IsCancellationRequested 属性都会设置为 true。

void Load(List<string> L)
{
    int i = 0;
    while (i < L.Count)
    {
        if (IsPaused != true)
        {
            if (IsCanceled != true)
            {
                asyncDoWork.ReportProgress(L[i]);
                Thread.Sleep(1000);
                i++;
            }
            else
            {
                if (MessageBox.Show("Do You Want To Cancel The Process...?", 
                    "Question", MessageBoxButton.YesNo, 
                    MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    //  If the owning object calls Cancel on the
                    //  CancellationTokenSource, the IsCancellationRequested
                    //  property on every copy of the cancellation token is set to true.
                    cnslTokSrc.Cancel();
                    if (cnslTokSrc.IsCancellationRequested)
                    {
                        break;
                    }
                }
                else
                {
                    IsCanceled = false;
                }
            }
        }
    }
}

关注点

即使 TPL 非常先进,它也有点像 Legacy 代码,但区别在于 TPL 比 Legacy 代码更容易,只需在一行中调用该进程。 但不了解 Legacy 代码,TPL 就很复杂。

© . All rights reserved.