내 문제 : .NET 4 및 WinForms 응용 프로그램에서 TPL을 사용하고 싶습니다.나는 기다리지 않고 처리되지 않은 예외를 즉각 ( "빨리 던지기") 승격시키는 작업 계속이 필요하다.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
연속체에서 예외가 처리되지 않으면 즉시 throw됩니다.Excecute
방법.
.NET 4에서 동일한 동작을 달성하는 방법async/await
지원하다?
우선, async-await를 .Net 4.0과 함께 사용하는 것이 가능하다는 것을 알아야합니다.Microsoft.Bcl.Async
하지만이 기능이 없으면 다음 작업으로 계속할 수 있습니다.ContinueWith
예외가있을 때만 실행하도록하십시오.TaskContinuationOptions.OnlyOnFaulted
Me.LongWork().ContinueWith(Sub(task) MsgBox(task.Exception.Message), CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted)
1) 사용 가능Microsoft.Bcl.Async
i3arnon이 제안한대로.
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
목표에SynchronizationContext
따라서 TPL의 예외 트래핑 메커니즘을 피할 수 있습니다. 그것은 빠르고 동기식에서 멀리 떨어져 있지만 적어도 그것은 작업 처리를 기다리는 것보다 더 잘 동작합니다.
Task.Wait
그러나 TPL을 사용하여 시작하는 것은 무의미합니다. - i3arnonWait
트릭을하지만, 내가 원하지 않는 UI 스레드를 차단합니다. 나는 & quot;Wait
& quot; 예외가 발생하면 곧. 계속해서Wait
다시 말하면 처리되지 않은 예외가 TPL에 걸리기 때문입니다. - mancze