我正在尝试通过在WCF中实现回调来显示在服务器上运行的SSIS包的进度。这是有道理的;在几个侦听器事件已经发生之后(在初始SSIS包执行调用后大约30秒),OperationContext.Current基本上返回null。这是我正在使用的一些代码:
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
我正在使用net 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 :(得分: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.Current被设置为null)。
我通过简单地默认一个空代表来修复它,即:
public PackageProgressChangedHandler OnPackageProgress = delegate { };
public PackagePostExecuteHandler OnPackagePostExecute = delegate { };