投稿者 mayopee  (社会人) 投稿日時 2020/5/29 10:45:50
るきお様、ありがとうございます。

あれから、色々と待機時間を変えて試行錯誤したのですが、やはり時間で待機する方法では
失敗する場合があり、実務では使えないと判断しました。

るきお様のご指摘の通リ、フラグ管理にしてみたら、今のところ100%成功しています。
これで、当面運用したいと思います。色々、ご指導ありがとうございました。
テスト用に使ったコードをアップしておきます。

Imports System.Threading
Public Class Form1
    Private _TV As New TreeView With {.Dock = DockStyle.Fill}
    Private _LB As New ListBox With {.Dock = DockStyle.Fill}
    Private _cts As CancellationTokenSource
    'Task実行中を示すフラグ 
    Private _IsTaskRunning As Boolean = False
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim sp As New SplitContainer With {.Dock = DockStyle.Fill}
        Dim root As New TreeNode("Task Cancel")
        Dim tn1 As New TreeNode("1")
        Dim tn2 As New TreeNode("2")
        Dim tn3 As New TreeNode("ListBox Clear")
        root.Nodes.AddRange({tn1, tn2, tn3})
        _TV.Nodes.Add(root)
        sp.Panel1.Controls.Add(_TV)
        sp.Panel2.Controls.Add(_LB)
        Controls.Add(sp)
        root.Expand()
        _TV.SelectedNode = root
        AddHandler _TV.AfterSelect, AddressOf TreeView_AfterSelect
        KeyPreview = True
        AddHandler Me.KeyDown, Sub(o, k)
                                   If k.KeyCode = Keys.Escape Then
                                       _cts?.Cancel()
                                   End If
                               End Sub
    End Sub
    Private Async Sub TreeView_AfterSelect(sender As Object, e As TreeViewEventArgs)
        Try
            If _IsTaskRunning Then _cts.Cancel()
            While _IsTaskRunning
                Await Task.Delay(10)
            End While
            _cts = New CancellationTokenSource
            Select Case e.Node.Text
                Case "1"
                    Await Task.Run(Sub()
                                       _IsTaskRunning = True
                                       For Each item In Enumerable.Range(1, 10000)
                                           Task.Delay(1).Wait()
                                           If _cts.Token.IsCancellationRequested Then
                                               Invoke(Sub() _LB.Items.Add("1 キャンセル ★★★★★★★★★★★★★★★★★★★★★★★★"))
                                               Return
                                           End If
                                           SetText($"Node1({item})")
                                       Next
                                   End Sub, _cts.Token)
                Case "2"
                    Await Task.Run(Sub()
                                       _IsTaskRunning = True
                                       For Each item In Enumerable.Range(1, 10000)
                                           Task.Delay(1).Wait()
                                           If _cts.Token.IsCancellationRequested Then
                                               Invoke(Sub() _LB.Items.Add("2 キャンセル ★★★★★★★★★★★★★★★★★★★★★★★★"))
                                               Return
                                           End If
                                           SetText($"Node2({item})")
                                       Next
                                   End Sub, _cts.Token)
                Case "ListBox Clear"
                    _LB.Items.Clear()
            End Select
        Finally
            _IsTaskRunning = False
            _cts.Dispose()
        End Try
    End Sub
    Private Sub SetText(s As String)
        If InvokeRequired Then
            Invoke(Sub() SetText(s))
        Else
            _LB.Items.Add(s)
        End If
    End Sub
End Class