私の問題:私は.NET 4のWinFormsアプリケーションでTPLを使いたい待っているのではなく、未処理の例外を即座に上げる( "fast throw")ためのタスク継続が必要です。GCを集めるTask。出来ますか?
.NET 4.5ではasync/awaitそれは書くことが可能ですサポート:
Public Class AwaitForm
    Inherits Form
    Private Async Sub Execute()
        Dim uiScheduler = TaskScheduler.FromCurrentSynchronizationContext()
        Try
            Await Me.LongWork().
                ContinueWith(Sub(t) Me.LongWorkCompleted(), uiScheduler)
        Catch ex As Exception
            ' yay, possible to handle here
            ' eg. MsgBox(ex.Message)
            Throw
        End Try
    End Sub
    Private Async Function LongWork() As Task
        Await Task.Delay(1000)
    End Function
    Private Sub LongWorkCompleted()
        Throw New Exception("Ups")
    End Sub
End Class
で処理されないと、継続中の例外がただちにスローされます。Excecute方法。
なしで.NET 4で同じ動作を実現する方法async/awaitサポート?
まず最初に、.Net 4.0でasync-awaitを使用することが可能であることを知っておくべきです。Microsoft.Bcl.Async
しかし、それがなければ、次のようにしてタスクに継続を追加できます。ContinueWithそして、例外があったときだけそれを走らせますTaskContinuationOptions.OnlyOnFaulted
Me.LongWork().ContinueWith(Sub(task) MsgBox(task.Exception.Message), CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted)
1)どちらでも使えますMicrosoft.Bcl.Asynci3arnonが示唆しているように。
2)または、あなたが追加のライブラリを参照したくないならば、私はに基づく解決策を思い付きましたasync/await。背後にある魔法は幸運ですが、それは私が持っていることが最高です。
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Threading
Public Module TaskExtensions
    ''' <summary>Throws the exception on the current SynchronizationContext or ThreadPool if there is none.</summary>
    ''' <param name="task">Task whose faulted continuation should throw exception.</param>
    <Extension()>
    Public Sub ThrowOnFaulted(task As Task)
        Dim context = SynchronizationContext.Current
        ThrowOnFaulted(task, context)
    End Sub
    ''' <summary>Throws the exception on the ThreadPool in given context.</summary>
    ''' <param name="task">Task whose faulted continuation should throw exception.</param>
    ''' <param name="targetContext">The target context on which to propagate the exception. Null to use the ThreadPool.</param>
    <Extension()>
    Public Sub ThrowOnFaulted(task As Task, targetContext As SynchronizationContext)
        task.ContinueWith(Sub(t) ThrowOnFaultedCore(t, targetContext), TaskContinuationOptions.OnlyOnFaulted)
    End Sub
    ''' <remarks>Taken from System.RunTime.CompilerServices.AsyncServices.</remarks>
    Private Sub ThrowOnFaultedCore(task As Task, targetContext As SynchronizationContext)
        Dim exception = task.Exception
        If targetContext IsNot Nothing Then
            Try
                targetContext.Post(Sub(state) Throw DirectCast(state, Exception), exception)
                Return
            Catch ex As Exception
                exception = New AggregateException({exception, ex})
            End Try
        End If
        ThreadPool.QueueUserWorkItem(Sub(state) Throw DirectCast(state, Exception), exception)
    End Sub
End Module
それは要件を満たしています - 例外は "速く"投げられそして処理することができます。例外はPostターゲットにedSynchronizationContextしたがって、TPLの例外トラップメカニズムを回避します。高速で同期的ではありませんが、少なくともタスクの破棄を待つよりも動作が優れています。
Task.Waitしかし、それからTPLを使用して始めても意味がありません。 - i3arnonWaitトリックを行いますが、私はしたくないUIスレッドをブロックします。 &quot;したいWait&quot;例外がスローされるとすぐに、と継続しているWait繰り返しますが、未処理の例外はTPLによってトラップされます。 - mancze