2009-11-09 58 views
1

我目前正試圖通過在WCF中實現回調來顯示服務器上運行的SSIS包的進度。這正在努力一點;基本上,OperationContext.Current在一些偵聽器事件已經發生之後(初始SSIS包執行調用大約30秒後)返回null。下面是一些我使用的代碼:WCF回調實現:服務始終返回空操作上下文

WCF服務方法:

var dts = new Microsoft.SqlServer.Dts.Runtime.Application(); 

PackageEventListener listener = new PackageEventListener(); 
listener.OnPackageProgress += new PackageEventListener.PackageProgressChangedHandler(listener_OnPackageProgress); 
... 
if (package.Execute(null, null, listener, null, null) == DTSExecResult.Failure) 
... 

private static void listener_OnPackageProgress(object package, EventArgs packageinfo) 
{ 
    var context = System.ServiceModel.OperationContext.Current; 
    if (context == null) return; 

    IXLoadMarriageCallback callback = context.GetCallbackChannel<IXLoadMarriageCallback>(); 
    if (callback != null) 
    { 
     PackageProgressEventArgs eventArgs = (PackageProgressEventArgs)packageinfo; 
     callback.OnProgressCallback(eventArgs.ProgressDescription); 
    } 
} 

public interface IXLoadMarriageCallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void OnProgressCallback(string message); 
} 

(PackageEventListener是從Microsoft.SqlServer.Dts.Runtime.DefaultEvents繼承的類)

服務被標記爲:

[ServiceBehavior(
    InstanceContextMode = InstanceContextMode.PerSession, 
    ConcurrencyMode = ConcurrencyMode.Reentrant 
)] 
public class IntegrationServicesService : IIntegrationServicesService 

,服務接口被標記如下:

[ServiceContract(
    CallbackContract = typeof(Business.IXLoadMarriageCallback), 
    SessionMode = SessionMode.Required 
)] 
public interface IIntegrationServicesService 

我使用的是TCP淨綁定,服務端配置如下:

<bindings> 
    <netTcpBinding> 
     <binding name="LongReliableTCPBinding" 
      closeTimeout="10:01:00" openTimeout="10:01:01" receiveTimeout="08:00:01" sendTimeout="08:00:02" 
      transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" 
      hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="4194304" maxBufferSize="4194304" maxConnections="10" maxReceivedMessageSize="4194304"> 
      <readerQuotas maxDepth="32" maxStringContentLength="4194304" maxArrayLength="4194304" maxBytesPerRead="4194304" maxNameTableCharCount="4194304" /> 
      <reliableSession ordered="true" inactivityTimeout="08:00:03" enabled="true" /> 
      <security mode="Transport"> 
       <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
       <message clientCredentialType="Windows" /> 
      </security> 
     </binding> 
    </netTcpBinding> 
</bindings> 

我看不出有任何異常被拋出。對於相當不完整的代碼示例抱歉,因爲有很多事情正在進行(只是爲了獲得進度的指示!)。

按照要求,這裏的一些調用服務方法的客戶端代碼(這是一個主持人):

public class XLoadPresenter : IIntegrationServicesServiceCallback, IDisposable 
{ 
    private IXLoadView view; 
    private readonly IIntegrationServicesServiceClient integrationServicesServiceClient; 
    private readonly IXLoadServiceClient xloadServiceClient; 

    public XLoadPresenter(IXLoadServiceClient xloadServiceClient) 
    { 
     var context = new System.ServiceModel.InstanceContext(this); 
     this.integrationServicesServiceClient = new IntegrationServicesServiceClient(context); 

     this.xloadServiceClient = xloadServiceClient; 
    } 

    ... 

    private void InvokeXLoadMarriages() 
    { 
     integrationServicesServiceClient.BeginXLoadMarriage(view.Database, OnEndXLoadMarriages, null); 
    } 
    ... 
} 
+0

你能提供從代理檢索代碼片段固定的呢?你確定你通過'InstanceContext'傳遞了非空回調實例嗎? – 2009-11-09 04:24:45

回答

1

想通了什麼事。問題就出在我執行DefaultEvents類:

public class PackageEventListener : DefaultEvents 
{ 
    public PackageProgressChangedHandler OnPackageProgress; 
    public PackagePostExecuteHandler OnPackagePostExecute; 

    public delegate void PackageProgressChangedHandler(object package, EventArgs packageInfo); 
    public delegate void PackagePostExecuteHandler(object package, EventArgs packageInfo); 

    public override void OnProgress(TaskHost taskHost, string progressDescription, int percentComplete, int progressCountLow, int progressCountHigh, string subComponent, ref bool fireAgain) 
    { 
     OnPackageProgress(this, new PackageProgressEventArgs(taskHost, progressDescription, subComponent)); 

     base.OnProgress(taskHost, progressDescription, percentComplete, progressCountLow, progressCountHigh, subComponent, ref fireAgain); 
    } 

    public override void OnPostExecute(Executable exec, ref bool fireAgain) 
    { 
     OnPackagePostExecute(this, new PackagePostExecuteEventArgs(exec)); 

     base.OnPostExecute(exec, ref fireAgain); 
    } 
} 

我重寫OnPostExecute但在這個問題我已經列出的代碼示例中沒有附加一個處理程序,它,即:

listener.OnPackageProgress += new PackageEventListener.PackageProgressChangedHandler(listener_OnPackageProgress); 

但沒有:

listener.OnPackagePostExecute += PackageEventListener.PackagePostExecuteHandler(listener_OnPackagePostExecute); 

於是重寫OnPostExecute是正在報道扔了「隱藏」的空引用異常(在這個意義上也不例外和OperationContext.Cu rrent被設置爲空)。

我通過簡單的違約空的代表,即:

public PackageProgressChangedHandler OnPackageProgress = delegate { }; 
public PackagePostExecuteHandler OnPackagePostExecute = delegate { };