Can I intialize DelayActivity.InitializeTimeoutDuration from the data Base
Hello, Mu question is how to intialize the DelayActivity.InitializeTimeoutDuration from a data Base value?
Hello, Mu question is how to intialize the DelayActivity.InitializeTimeoutDuration from a data Base value?
There are many possible ways to do this.. the simplest would be to execute the SQL inside the InitializeTimeoutDuration code, eg.
Private Sub delayActivity1_InitializeTimeoutDuration(ByVal sender As System.Object, ByVal e As System.EventArgs)
' execute SQL to get timeout value here
' ... e.g.
' record
Me.delayActivity1.TimeoutDuration = New TimeSpan(hours, 0, 0)
End Sub
If you are using the delay in a StateMachine, While, CAG or code separated workflow using Me.delayActivity1.TimeoutDuration won’t work.The first three because of spawned context and with code separated workflows because the private variable Me.delayActivity1 doesn’t exist. Instead the sender parameter for the InitializeTimeoutDuration event will always be the currently running instance of the Delay.Cast it to a DelayActivity and set the value on the TimeoutDuration property.
InitializeTimeoutDuration is an event that is fired just prior to the Delay activity executing.This allows you to add an event handler in the workflow / custom activity where you can do things like set the TimeoutDuration to a new value.After adding a delay activity double click on it and the handler will be generated for you.To change the length of the TimeoutDuration to 5 minutes your VB code to set the value would look like:
Private Sub delayActivity1_InitializeTimeoutDuration(ByVal sender As System.Object, ByVal e As System.EventArgs)
CType(sender, DelayActivity).TimeoutDuration = TimeSpan.FromMinutes(5)
End Sub
For C# it would look like this:
private void delayActivity1_InitializeTimeoutDuration(object sender, EventArgs e)
{
(sender as DelayActivity).TimeoutDuration = TimeSpan.FromMinutes(5);
}
GetActivityByName is used to get an activity using some other activity as a starting point. The activity that you start with has a lot to do with the results you will be getting. As an example I created an activity deriving from Activity that has one string property named MyProperty and two events named Before and After. The Execute method looks like the following:
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
RaiseEvent(BeforeEvent, this, new EventArgs());
RaiseEvent(AfterEvent, this, new EventArgs());
return base.Execute(executionContext);
}
Add the custom activity to a While that is contain in a SequentialWorkflow. Set the while activity so it will execute atleast once. Next add the following handlers for the before and after events:
private void AfterInvoking(object sender, EventArgs e)
{
Console.WriteLine(string.Format("this.traceMyProperty1.MyProperty value is '{0}'", this.traceMyProperty1.MyProperty));
Console.WriteLine(string.Format("(this.GetActivityByName(\"traceMyProperty1\") as TraceMyProperty).MyProperty value is '{0}'", (this.GetActivityByName("traceMyProperty1") as TraceMyProperty).MyProperty));
Console.WriteLine(string.Format("((sender as Activity).GetActivityByName(\"traceMyProperty1\") as TraceMyProperty).MyProperty value is '{0}'", ((sender as Activity).GetActivityByName("traceMyProperty1") as TraceMyProperty).MyProperty));
Console.WriteLine(string.Format("(sender as TraceMyProperty).MyProperty value is '{0}'", (sender as TraceMyProperty).MyProperty));
}
private void BeforeInvoking(object sender, EventArgs e)
{
(sender as TraceMyProperty).MyProperty = "new value";
}
The results when you run the workflow will be the following for each iteration of the while:
this.traceMyProperty1.MyProperty value is ''
(this.GetActivityByName("traceMyProperty1") as TraceMyProperty).MyProperty value is ''
((sender as Activity).GetActivityByName("traceMyProperty1") as TraceMyProperty).MyProperty value is 'new value'
(sender as TraceMyProperty).MyProperty value is 'new value'
So with GetActivityByName you have the same issues that you have when you use the private variable that is created when using code workflows. Get in the habit of using the sender, which in most cases should be the activity that the event handler is for. Then you won’t run into any issues when you work with activities that spawn a new execution context to run their children.
Interesting, so if you call this.GetActivityByName, the search starts from the root workflow (this), so you'll still get the template, not the spawned context.
What if the sender is not the activity you need to modify? Then I assume that you'd need to do some combination of casting the sender and calling GetActivityByName to get the appropriate context of the other activity, depending on how the two activities are related in the "subtree" of activity contexts.
Sorry for the delay in responding. If the sender is not the activity you need to modify then you need to get to a common parent using the sender and then use GetActivityByName. Calling GetActivityByName on the sender will return the template activity also if the activity you are searching for is not a child of the sender.Try the following to demonstrate this.
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
//((sender as Activity).Parent.GetActivityByName("delayActivity1") as DelayActivity).TimeoutDuration = new TimeSpan(0, 0, 5);
((sender as Activity).GetActivityByName("delayActivity1") as DelayActivity).TimeoutDuration = new TimeSpan(0, 0, 5);
}
private void delayActivity1_InitializeTimeoutDuration(object sender, EventArgs e)
{
Console.WriteLine((sender as DelayActivity).TimeoutDuration.ToString());
}
If you look at the output after running it twice you will see the following:
00:00:00
00:00:05
If you instead use the commented line instead you will get the correct instance and the result will always be the following:
00:00:05
Hope this helps.