Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Gäller för:SQL Server
SSIS Integration Runtime i Azure Data Factory
Integration Services körtidsmotor möjliggör att paket, uppgifter och andra typer av behållare kan pausas under körning genom att använda brytpunkter. Användningen av brytpunkter låter dig granska och rätta fel som hindrar din applikation eller dina uppgifter från att fungera korrekt. Breakpoint-arkitekturen gör det möjligt för klienten att utvärdera körtidsvärdet för objekt i paketet vid definierade exekveringspunkter medan uppgiftsbearbetningen är pausad.
Anpassade uppgiftsutvecklare kan använda denna arkitektur för att skapa anpassade brytpunktsmål genom att använda gränssnittet IDTSBreakpointSite och dess föräldragränssnitt, IDTSSuspend. Gränssnittet IDTSBreakpointSite definierar interaktionen mellan körtidsmotorn och uppgiften för att skapa och hantera anpassade brytpunktsplatser eller mål. Gränssnittet IDTSSuspend tillhandahåller metoder och egenskaper som anropas av körtidsmotorn för att meddela uppgiften att pausa eller återuppta sin exekvering.
En brytpunktsplats eller mål är en punkt i utförandet av uppgiften där bearbetningen kan avbrytas. Användare väljer bland tillgängliga brytpunktsplatser i dialogrutan Sätt brytpunkter . Till exempel, utöver standardbrytpunktsalternativen, erbjuder Foreach Loop Container alternativet "Bryt i början av varje iteration av loopen".
När en uppgift når ett brytpunktsmål under körningen utvärderar den brytpunktmålet för att avgöra om en brytpunkt är aktiverad. Detta indikerar att användaren vill att exekveringen ska stanna vid den brytpunkten. Om brytpunkten är aktiverad höjer uppgiften händelsen OnBreakpointHit till körtidsmotorn. Körtidsmotorn svarar på händelsen genom att anropa Suspend-metoden för varje uppgift som för närvarande körs i paketet. Exekveringen av uppgiften återupptas när körtiden anropar ResumeExekvering-metoden för den avbrutna uppgiften.
Uppgifter som inte använder brytpunkter bör ändå implementera IDTSBreakpointSite och IDTSSuspend gränssnitt. Detta säkerställer att uppgiften avbryts korrekt när andra objekt i paketet väcker OnBreakpointHit händelser.
IDTSBreakpointSite-gränssnitt och BreakpointManager
Uppgifter skapar brytpunktsmål genom att anropa CreateBreakpointTarget metoden , BreakpointManageroch ger ett heltals-ID och en strängbeskrivning som parametrar. När uppgiften når den punkt i sin kod som innehåller ett brytpunktsmål, utvärderar den brytpunktsmålet genom att använda metoden IsBreakpointTargetEnabled för att avgöra om den brytpunkten är aktiverad. Om det stämmer, meddelar uppgiften körtidsmotorn genom att höja händelsen OnBreakpointHit .
Gränssnittet IDTSBreakpointSite definierar en enda metod, AcceptBreakpointManager, som anropas av körtidsmotorn under uppgiftsskapandet. Denna metod tillhandahåller objektet som parameter BreakpointManager , vilket sedan används av uppgiften för att skapa och hantera dess brytpunkter. Tasks bör lagra det BreakpointManager lokalt för användning under Validate- och Execute-metoderna .
Följande exempelkod visar hur man skapar ett brytpunktsmål genom att använda .BreakpointManager Provet anropar OnBreakpointHit metoden för att höja händelsen.
public void AcceptBreakpointManager( BreakpointManager breakPointManager )
{
// Store the breakpoint manager locally.
this.bpm = breakPointManager;
}
public override DTSExecResult Execute( Connections connections,
Variables variables, IDTSComponentEvents events,
IDTSLogging log, DtsTransaction txn)
{
// Create a breakpoint.
this.bpm.CreateBreakPointTarget( 1 , "A sample breakpoint target." );
...
if( this.bpm.IsBreakpointTargetEnabled( 1 ) == true )
events.OnBreakpointHit( this.bpm.GetBreakpointTarget( 1 ) );
}
Public Sub AcceptBreakpointManager(ByVal breakPointManager As BreakpointManager)
' Store the breakpoint manager locally.
Me.bpm = breakPointManager
End Sub
Public Overrides Function Execute(ByVal connections As Connections, _
ByVal variables As Variables, ByVal events As IDTSComponentEvents, _
ByVal log As IDTSLogging, ByVal txn As DtsTransaction) As DTSExecResult
' Create a breakpoint.
Me.bpm.CreateBreakPointTarget(1 , "A sample breakpoint target.")
If Me.bpm.IsBreakpointTargetEnabled(1) = True Then
events.OnBreakpointHit(Me.bpm.GetBreakpointTarget(1))
End If
End Function
IDTSSuspend-gränssnittet
Gränssnittet IDTSSuspend definierar de metoder som anropas av körtidsmotorn när den pausar eller återupptar exekveringen av en uppgift. Gränssnittet IDTSSuspend implementeras av gränssnittet IDTSBreakpointSite , och dess metoder Suspend och ResumeExecution överskrivs vanligtvis av den anpassade uppgiften. När körtidsmotorn tar emot en OnBreakpointHit-händelse från en uppgift, anropar den Suspend-metoden för varje körande uppgift och meddelar uppgifterna att pausa. När klienten återupptar exekveringen anropar körtidsmotorn metoden ResumeExecution för de uppgifter som är avstängda.
Att pausa och återuppta uppgiftskörning innebär att man pausar och återupptar uppgiftens exekveringstråd. I managed code gör du detta med ManualResetEvent-klassen i System.Threading-namnrymden i .NET Framework.
Följande kodexempel visar på paus och återupptagande av uppgiftsutförande. Observera att Execute-metoden har ändrats från det föregående kodexemplet, och exekveringstråden pausas när brytpunkten aktiveras.
private ManualResetEvent m_suspended = new ManualResetEvent( true );
private ManualResetEvent m_canExecute = new ManualResetEvent( true );
private int m_suspendRequired = 0;
private int m_debugMode = 0;
public override DTSExecResult Execute( Connections connections, Variables variables, IDTSComponentEvents events, IDTSLogging log, DtsTransaction txn)
{
// While a task is not executing, it is suspended.
// Now that we are executing,
// change to not suspended.
ChangeEvent(m_suspended, false);
// Check for a suspend before doing any work,
// in case the suspend and execute calls
// were initiated at virtually the same time.
CheckAndSuspend();
CheckAndFireBreakpoint( componentEvents, 1);
}
private void CheckAndSuspend()
{
// Loop until we can execute.
// The loop is required rather than a simple If
// because there is a time between the return from WaitOne and the
// reset that we might receive another Suspend call.
// Suspend() will see that we are suspended
// and return. So we need to rewait.
while (!m_canExecute.WaitOne(0, false))
{
ChangeEvent(m_suspended, true);
m_canExecute.WaitOne();
ChangeEvent(m_suspended, false);
}
}
private void CheckAndFireBreakpoint(IDTSComponentEvents events, int breakpointID)
{
// If the breakpoint is enabled, fire it.
if (m_debugMode != 0 && this.bpm.IsBreakpointTargetEnabled(breakpointID))
{
// Enter a suspend mode before firing the breakpoint.
// Firing the breakpoint will cause the runtime
// to call Suspend on this task.
// Because we are blocked on the breakpoint,
// we are suspended.
ChangeEvent(m_suspended, true);
events.OnBreakpointHit(this.bpm.GetBreakpointTarget(breakpointID));
ChangeEvent(m_suspended, false);
}
// Check for a suspension for two reasons:
// 1. If we are at a point where we could fire a breakpoint,
// we are at a valid suspend point. Even if we didn't hit a
// breakpoint, the runtime may have called suspend,
// so check for it.
// 2. Between the return from OnBreakpointHit
// and the reset of the event, it is possible to have
// received a suspend call from which we returned because
// we were already suspended. We need to be sure it is okay
// to continue executing now.
CheckAndSuspend();
}
static void ChangeEvent(ManualResetEvent e, bool shouldSet)
{
bool succeeded;
if (shouldSet)
succeeded = e.Set();
else
succeeded = e.Reset();
if (!succeeded)
throw new Exception("Synchronization object failed.");
}
public bool SuspendRequired
{
get {return m_suspendRequired != 0;}
set
{
// This lock is also taken by Suspend().
// Because it is possible for the package to be
// suspended and resumed in quick succession,
// this property might be set before
// the actual Suspend() call.
// Without the lock, the Suspend() might reset the canExecute
// event after we set it to abort the suspension.
lock (this)
{
Interlocked.Exchange(ref m_suspendRequired, value ? 1 : 0);
if (!value)
ResumeExecution();
}
}
}
public void ResumeExecution()
{
ChangeEvent( m_canExecute,true );
}
public void Suspend()
{
// This lock is also taken by the set SuspendRequired method.
// It prevents this call from overriding an
// aborted suspension. See comments in set SuspendRequired.
lock (this)
{
// If a Suspend is required, do it.
if (m_suspendRequired != 0)
ChangeEvent(m_canExecute, false);
}
// We can't return from Suspend until the task is "suspended".
// This can happen one of two ways:
// the m_suspended event occurs, indicating that the execute thread
// has suspended, or the canExecute flag is set,
// indicating that a suspend is no longer required.
WaitHandle [] suspendOperationComplete = {m_suspended, m_canExecute};
WaitHandle.WaitAny(suspendOperationComplete);
}
Private m_suspended As ManualResetEvent = New ManualResetEvent(True)
Private m_canExecute As ManualResetEvent = New ManualResetEvent(True)
Private m_suspendRequired As Integer = 0
Private m_debugMode As Integer = 0
Public Overrides Function Execute(ByVal connections As Connections, _
ByVal variables As Variables, ByVal events As IDTSComponentEvents, _
ByVal log As IDTSLogging, ByVal txn As DtsTransaction) As DTSExecResult
' While a task is not executing it is suspended.
' Now that we are executing,
' change to not suspended.
ChangeEvent(m_suspended, False)
' Check for a suspend before doing any work,
' in case the suspend and execute calls
' were initiated at virtually the same time.
CheckAndSuspend()
CheckAndFireBreakpoint(componentEvents, 1)
End Function
Private Sub CheckAndSuspend()
' Loop until we can execute.
' The loop is required rather than a simple if
' because there is a time between the return from WaitOne and the
' reset that we might receive another Suspend call.
' Suspend() will see that we are suspended
' and return. So we need to rewait.
Do While Not m_canExecute.WaitOne(0, False)
ChangeEvent(m_suspended, True)
m_canExecute.WaitOne()
ChangeEvent(m_suspended, False)
Loop
End Sub
Private Sub CheckAndFireBreakpoint(ByVal events As IDTSComponentEvents, _
ByVal breakpointID As Integer)
' If the breakpoint is enabled, fire it.
If m_debugMode <> 0 AndAlso Me.bpm.IsBreakpointTargetEnabled(breakpointID) Then
' Enter a suspend mode before firing the breakpoint.
' Firing the breakpoint will cause the runtime
' to call Suspend on this task.
' Because we are blocked on the breakpoint,
' we are suspended.
ChangeEvent(m_suspended, True)
events.OnBreakpointHit(Me.bpm.GetBreakpointTarget(breakpointID))
ChangeEvent(m_suspended, False)
End If
' Check for a suspension for two reasons:
' 1. If we are at a point where we could fire a breakpoint,
' we are at a valid suspend point. Even if we didn't hit a
' breakpoint, the runtime may have called suspend,
' so check for it.
' 2. Between the return from OnBreakpointHit
' and the reset of the event, it is possible to have
' received a suspend call from which we returned because
' we were already suspended. We need to be sure it is okay
' to continue executing now.
CheckAndSuspend()
End Sub
Shared Sub ChangeEvent(ByVal e As ManualResetEvent, ByVal shouldSet As Boolean)
Dim succeeded As Boolean
If shouldSet Then
succeeded = e.Set()
Else
succeeded = e.Reset()
End If
If (Not succeeded) Then
Throw New Exception("Synchronization object failed.")
End If
End Sub
Public Property SuspendRequired() As Boolean
Get
Return m_suspendRequired <> 0
End Get
Set
' This lock is also taken by Suspend().
' Because it is possible for the package to be
' suspended and resumed in quick succession,
' this property might be set before
' the actual Suspend() call.
' Without the lock, the Suspend() might reset the canExecute
' event after we set it to abort the suspension.
SyncLock Me
Interlocked.Exchange(m_suspendRequired,IIf(Value, 1, 0))
If (Not Value) Then
ResumeExecution()
End If
End SyncLock
End Set
End Property
Public Sub ResumeExecution()
ChangeEvent(m_canExecute,True)
End Sub
Public Sub Suspend()
' This lock is also taken by the set SuspendRequired method.
' It prevents this call from overriding an
' aborted suspension. See comments in set SuspendRequired.
SyncLock Me
' If a Suspend is required, do it.
If m_suspendRequired <> 0 Then
ChangeEvent(m_canExecute, False)
End If
End SyncLock
' We can't return from Suspend until the task is "suspended".
' This can happen one of two ways:
' the m_suspended event occurs, indicating that the execute thread
' has suspended, or the canExecute flag is set,
' indicating that a suspend is no longer required.
Dim suspendOperationComplete As WaitHandle() = {m_suspended, m_canExecute}
WaitHandle.WaitAny(suspendOperationComplete)
End Sub