我的工作流托管在IIS中。并且每个工作流都继承自asynccodeactivity。在BeginExecute中,我调用命令。Beginxxx,在执行结束时,我调用EndExecutexxx。我正在使用数据库访问块(DAAB)。
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
DbCommand command = null;
DbConnection dbConnection = null;
entlib.Database database;
try
{
database = EnterpriseLibraryContainer.Current.GetInstance<entlib.Database>(DatabaseName.Get(context));
dbConnection = database.CreateConnection();
command = dbConnection.CreateCommand();
command.CommandText = CommandText.Get(context);
command.CommandType = CommandType.Get(context);
//have removed few assignments here
context.UserState = new AsyncDbState(database, command);
}
catch (Exception e)
{
if (command != null)
command.Dispose();
if (dbConnection != null)
dbConnection.Dispose();
throw e;
}
return (database.Beginxxx(command, callback, state));
}
protected override TResult EndExecute(AsyncCodeActivityContext context, IAsyncResult iResult)
{
TResult result = default(TResult);
var userState = context.UserState as AsyncDbState;
try
{
result = (TResult)userState.Database.Endxxx(iResult);
}
finally
{
if (null != userState && null != userState.Command)
userState.Command.Dispose();
}
return result;
}
偶尔它会在事件日志中抛出错误并终止整个应用程序池。在@Will发表评论后,我确实捕获了内部异常,并注意到发生了实际错误
在继承自asyncnativeactivity的另一个活动的BeginExecute中,我有
var task = AsyncFactory<IDataReader>.Action(() => ExecuteMdxQuery(connectionStringSettings, mdxQuery, commandTimeout, cancellationToken), cancellationToken);
return AsyncFactory<IDataReader>.ToBegin(task, callback, state);
and AsyncFactory looks like this
public static Task<TResult> Action(Func<TResult> actionMethod,CancellationToken token)
{
TaskFactory factory = new TaskFactory();
//TaskFactory factory = new TaskFactory(scheduler);
return factory.StartNew<TResult>(() => actionMethod(), token);
}
public static IAsyncResult ToBegin(Task<TResult> task, AsyncCallback callback, object state)
{
var tcs = new TaskCompletionSource<TResult>(state);
var continuationTask = task.ContinueWith(t =>
{
if (task.IsFaulted)
{
tcs.TrySetException(task.Exception.InnerExceptions);
}
else if (task.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(task.Result);
}
发生未处理的异常,进程被终止。
发生未处理的异常,进程被终止。
应用程序ID:/LM/W3SVC/1/ROOT/workflowservice
进程ID:7140
异常:System.AggregateException
消息:通过等待任务或访问其exception属性,都没有观察到任务的异常。结果,终结器线程重新抛出了未观察到的异常。
StackTrace:位于System.Threading.Tasks.TaskExceptionHolder.Finalize()
InnerException:Microsoft.AnalysisServices.AomdClient.AdomdErrorResponseException
消息:服务器:当前操作已取消,因为事务中的另一个操作失败。
StackTrace:位于Microsoft.AnalysisServices.AdomdClient.AdomdConnection.XmlaClientProvider.Microsoft.AAnalysisServices.AdomdClient.IExecuteProvider.ExecuteTabular(CommandBehavior行为,ICommandContentProvider内容提供程序,AdomdPropertyCollection命令属性,IDataParameterCollection参数)位于Microsoft.AnalysisServices.AdomdClient.AdomdCommand.ExecuteReader(CommandBehavior行为)在WorkflowActivity.AsyncExecuteSafeReader.ExecuteMdxQuery(字符串connectionStringName,字符串mdxQuery,可为空的1 commandTimeout, CancellationToken cancellationToken) in d:B69SourcesInfrastructureWorkflowActivityAsyncExecuteSafeReader.cs:line 222
at AsyncExecuteSafeReader.ExecuteMdxQuery(String connectionStringName, String mdxQuery, Nullable
1 commandTimeout,CancellationToken cancellionToken),位于d:\B\69\Sources\Infrastructure \WorkflowActivity\ AsyncExecute SafeReader.cs:line 239位于WorkflowActivity.AsyncExecuteSafeReader。<>c:\b\69\Sources\Infrastructure \WorkflowActivity\AsyncExecuteSafeReader.cs:line 180中的c__DisplayClassd.b_a()位于System.Threading.Tasks.Task`1.InvokeFuture(Object futureAsObj)在System.Threading.Tasks.Task.Execute()
第一个提示是这在IIS中发生。虽然在应用程序中,当您可能遇到多线程导致的问题时,这通常是显而易见的,但在IIS中则不然
IIS中的每个请求都由不同的线程提供服务。任何共享实例都将被多个线程命中。如果你没有预料到的话,这通常是个坏消息
因此,我的第一个猜测(不得不猜测,因为您的异常的调用堆栈被切断了;稍后会详细介绍)是您在不同的线程中使用线程不安全的代码。我怀疑它是以EnterpriseLibraryContainer.Current.GetInstance
为中心的,因为如果它不为每个线程存储实例,那么它将在线程之间共享相同的实例。你必须检查代码或文档。最简单的测试方法是在监视窗口中使用"生成对象ID",然后在两个不同的线程中比较EnterpriseLibraryContainer.Current.GetInstance
的结果。
清楚的是,您的异常正在丢失,因为您正在重新抛出异常,而不是让它消失。有关这种情况下的最佳实践的更多信息,请参阅此答案。
重新检查调用堆栈,它似乎仍然是一个多线程错误,但问题似乎是多个线程试图完成两个不同Task
s的执行。
消息:操作已完成
StackTrace:位于System.Activities.AsyncOperationContext.HShouldComplete()
某个地方正在尝试完成Task
的执行,但它已经完成了。在中,一个线程击败另一个线程完成异步操作。
在这一点上,如果没有异常的完整堆栈跟踪,就无法判断实际问题是什么以及问题发生在哪里。获取此信息的最佳方法是在代码中第一时间捕获异常并对其调用ToString()
,或者使用异常助手对话框上的"复制到剪贴板"链接(执行相同的操作,将其复制到剪贴板)。这很重要,因为你可以获得以下信息
- 异常类型
- 异常消息
- 堆栈跟踪
不仅针对您捕获的异常,而且针对由该异常包装的每个.InnerException
`很多时候那才是你真正的问题所在
在这种情况下,当您这样做时,您能够识别代码在哪里遇到了可重入性问题。
@Will,连接字符串中的Mars=false似乎已经解决了它。无法复制它。理论上是-查询返回的结果。并调用了end execute。但它也返回了另一个结果集?这就是调用回调的原因。但到那时已经调用了end execute。但话说回来,它是零星的。如果这个理论是真的,我的理解是它可能一直失败。到目前为止还没有崩溃。也有少数程序需要rowcount。我很感激你花时间对此发表评论并分享你的理论。学到了很多。