VB.NET Task の使い方

(Visual Studio 2015 版)

投稿日 2015/11/08

[Home] | VB.NET インデックス

概要

Task クラスを使うと非同期動作を簡単に記述できます。


サンプル

単純なタスクの例

次のサンプルは1つのタスクを起動して終了まで待機します。タスクが終了したらメッセージ "Done." を表示します。

''' <summary>
''' 単純なタスクの例
''' </summary>
Module Module1
    ''' <summary>
    ''' メイン
    ''' </summary>
    Sub Main()
        ' タスクを作成する。
        Dim t = New Task(AddressOf action1)
        ' タスクを開始。
        t.Start()
        ' タスクの終了を待機する。
        t.Wait()
        Console.WriteLine("Done.")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary>
    ''' タスクメソッド
    ''' </summary>
    Sub action1()
        Console.WriteLine("Sleep 1s")
        Threading.Thread.Sleep(1000)
    End Sub
    
End Module

2つのタスクを待機する例

このサンプルは、2つのタスクを起動し、2つが終了するのを待機します。両方が終了したらメッセージ "Done." を表示します。

Imports System.Threading

''' <summary<
''' 2つのタスクを待つ例
''' </summary<
Module Module1
    ''' <summary<
    ''' メイン
    ''' </summary<
    Sub Main()
        'タスク1と2を作成する。
        Dim t1 As Task = New Task(AddressOf Action1)
        Dim t2 As Task = New Task(AddressOf Action2)
        ' 2つのタスクを開始
        t1.Start()
        t2.Start()
        ' タスク1と2の終了を待機する。
        Task.WaitAll(t1, t2)
        ' 終了メッセージを表示
        Console.WriteLine("Done.")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary<
    ''' タスク1のメソッド
    ''' </summary<
    Sub Action1()
        Thread.Sleep(1000)
        Console.WriteLine("Action 1")
    End Sub
    
    ''' <summary<
    ''' タスク2のメソッド
    ''' </summary<
    Sub Action2()
        Thread.Sleep(1000)
        Console.WriteLine("Action 2")
    End Sub
End Module

タスクを途中で取り消すサンプル

CancellationToken オブジェクトをタスクの実行を途中で取り消すことができます。これを使うには、直接 CancellationToken をインスタンス化するのではなく CancellationTokenSource をインスタンス化して、その Token プロパティを使います。CancellationTokenSource の Cancel メソッドを実行すると取消トークンの IsCancellationRequested プロパティが True になり、取り消し要求があったことを知ることができます。

Imports System.Threading

''' <summary>
''' CancellationToken を使う例
''' </summary>
Module Module1
    ''' <summary>
    ''' メイン
    ''' </summary>
    Sub Main()
        ' CancellationTokenSource オブジェクトを作成する。
        Dim cs = New CancellationTokenSource()
        ' 取消トークンを渡したタスクを作成する。
        Dim t = New Task(AddressOf Action1, cs.Token)
        ' タスクを開始する。
        t.Start()
        ' 2秒後にタスクを取消する。
        Thread.Sleep(2000)
        cs.Cancel()
        ' タスクの終了を待機する。
        t.Wait()
        'タスクが終わったらメッセージを表示する。
        Console.WriteLine("Done.")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary>
    ''' 取消トークンを受け取るタスクメソッド
    ''' </summary>
    ''' <param name="token"></param>
    Sub Action1(ByVal token As CancellationToken)
        While Not token.IsCancellationRequested
            Thread.Sleep(500)
            Console.WriteLine("***")
        End While
    End Sub
End Module

タスクを連結するサンプル

Task クラスの ContinueWith メソッドを使用すると、あるタスクの後に実行する別のタスクを指定できます。この例では、タスク1を開始した後、ContinueWith メソッドでタスク2を作成して、タスク1を開始します。タスク1が終了すると、タスク2が自動的に開始されます。タスク2の完了を待機してメッセージ "Done." を表示しています。

Imports System.Threading

''' <summary>
'''  ContinueWith でタスクをつなげる例
''' </summary>
Module Module1

    Sub Main()
        ' 取消トークンの準備(この例では実際には使用しない)
        Dim cs = New CancellationTokenSource()
        ' 最初に実行するタスク
        Dim t1 = New Task(AddressOf Action1, cs.Token)
        ' 次に実行するタスク
        Dim t2 = t1.ContinueWith(AddressOf Action2, cs.Token)
        ' タスク1を開始
        t1.Start()
        ' タスク2の終了を待機
        t2.Wait()
        Console.WriteLine("Done.")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary>
    ''' タスク1
    ''' </summary>
    ''' <param name="token"></param>
    Sub Action1(ByVal token As CancellationToken)
        Thread.Sleep(800)
        Console.WriteLine("Acton 1")
    End Sub
    
    ''' <summary>
    ''' タスク2
    ''' </summary>
    ''' <param name="t"></param>
    ''' <param name="token"></param>
    Sub Action2(ByVal t As Task, ByVal token As CancellationToken)
        If token.IsCancellationRequested Then
            Return
        End If
        Thread.Sleep(400)
        Console.WriteLine("Acton 2")
    End Sub
End Module

タスクの実行結果を受け取るサンプル

これまでのサンプルは、タスクを実行させるだけで戻り値を受け取ることをしませんでした。このサンプルではタスクメソッドを関数型とすることで戻り値を受け取り表示します。

Imports System.Threading

''' <summary>
''' タスクの実行結果を受け取るサンプル
''' </summary>
Module Module1
    ''' <summary>
    ''' メイン
    ''' </summary>
    Sub Main()
        ' タスクを作成
        Dim t = New Task(Of String)(AddressOf Func1)
        ' タスクを開始する。
        t.Start()
        ' タスクの終了を待機する。
        t.Wait()
        'タスクの実行結果を表示する。
        Console.WriteLine(t.Result)
        Console.WriteLine("Done.")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary>
    ''' 値を返す関数型のタスクメソッド
    ''' </summary>
    ''' <returns>タスクの戻り値</returns>
    Function Func1() As String
        Thread.Sleep(1000)
        Return "Function 1"
    End Function
End Module

タスクにパラメータを渡すサンプル

タスクにパラメータを渡すこともできます。その場合は、直接 Task をインスタンス化するのではなく、TaskFactory(Of T) をインスタンス化してその StartNew メソッドでタスクを作成+開始します。TaskFactory(Of T) の T はパラメータの型です。

Imports System.Threading

''' <summary>
''' タスクにパラメータを渡す場合
''' </summary>
Module Module1
    ''' <summary>
    ''' メイン
    ''' </summary>
    Sub Main()
        ' TaskFactory(Of T) をインスタンス化。T はタスクへ渡すパラメータの型。
        Dim factory = New TaskFactory(Of String)
        ' TaskFactory(Of T) の StartNew メソッドを使ってタスクを作成+開始。
        ' ここでパラメータは "Param" である。
        Dim t = factory.StartNew(AddressOf Func1, "Param")
        ' タスクの終了を待機する。
        t.Wait()
        ' タスクの戻り値を表示する。
        Console.WriteLine("Done. " & t.Result)
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary>
    ''' パラメータを受け取り結果を返すタスクメソッド
    ''' </summary>
    ''' <param name="p"></param>
    ''' <returns></returns>
    Function Func1(ByVal p As Object) As String
        Thread.Sleep(1000)
        Return "Func1 " & p.ToString()
    End Function
End Module

Parallel クラスを使ってタスクを並行動作させる例

複数のタスクを並行動作させるには、Parallel クラスを使ったほうが簡単です。下のサンプルはParallel クラスを使って3つのタスクを並行動作させています。

Imports System.Threading

''' <summary>
''' Parallel クラスを使って3つのタスクを並行動作させる例
''' </summary>
Module Module1
    ''' <summary>
    ''' メイン
    ''' </summary>
    Sub Main()
        ' 2つの Action1 と 1つの Action2 を起動する。
        Parallel.Invoke(AddressOf Action1, AddressOf Action1, AddressOf Action2)
        ' すべてのタスクが終了したらメッセージを表示する。
        Console.WriteLine("Done.")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub
    
    ''' <summary>
    ''' 1秒待機してメッセージを表示するメソッド
    ''' </summary>
    Sub Action1()
        Thread.Sleep(1000)
        Console.WriteLine("Action 1")
    End Sub
    
    ''' <summary>
    ''' 2秒待機してメッセージを表示するメソッド
    ''' </summary>
    Sub Action2()
        Thread.Sleep(2000)
        Console.WriteLine("Action 2")
    End Sub
End Module

 

 


 

 開設 2014年12月   著作権 2014-2015 bonk.red  連絡先: こちらからメッセージを送ってください。

 このページの先頭へ..