2012-09-11 62 views
2

我有同样的问题,因为this question MSDN上,但我不明白的解决方案,因为它仍然是不明确的,我如果罗马吻的解决方案将正确地更换一个端点地址,而一个单一的工作流程实例正在并发执行。解决端点绑定动态工作流

当内部Send活动被安排由具有某个enpoint地址的一个线程执行时,该地址是否会被另一个线程覆盖,该另一个线程使用不同的端点地址调度相同的活动?纠正我,如果我错了,但我相信它会,因为Send.Endpoint是一个普通的财产反对势必任何当前的工作流执行上下文是InArgument<Endpoint>

有人可以摆脱更多的光线进入呢?

UPDATE

我测试的罗马之吻提供的解决方案,而且事实证明,由于预期在我的情况下它不能正常工作。我修改Execute方法如下:

protected override void Execute(NativeActivityContext context) 
{ 
    Thread.Sleep(Address.Get(context).EndsWith("1") ? 1000 : 0); 

    Body.Endpoint.Binding = GetBinding(Binding.Get(context)); 
    Body.Endpoint.AddressUri = new Uri(Address.Get(context)); 

    Thread.Sleep(Address.Get(context).EndsWith("1") ? 0 : 3000); 
    var address = Address.Get(context) + " => " + Body.Endpoint.AddressUri; 
    Console.WriteLine(address); 
    Thread.Sleep(10000); 

    context.ScheduleActivity(Body); 
} 

冉这个测试:

static void Main(string[] args) 
{ 
    // Workflow1 is just a SendScope wrapped around by a Sequence with single Address input argument exposed 
    var workflow = new Workflow1(); 
    Task.WaitAll(
     Task.Run(() => WorkflowInvoker.Invoke(workflow, new Dictionary<string, object> { { "Address", @"http://localhost/1" } })), 
     Task.Run(() => WorkflowInvoker.Invoke(workflow, new Dictionary<string, object> { { "Address", @"http://localhost/2" } }))); 

    Console.ReadLine(); 
} 

我得到的结果是:

http://localhost/1 => http://localhost/1

http://localhost/2 => http://localhost/1

问题仍然是开放的:我怎么在运行时分配我Send活动的端点地址动态?

回答

1

这将使用CacheMetadata方法来设置该Send活动是设定在工作时如图所示,因为Send活动由工厂等创建的活动的该实例适当结合。

包括内容柜面链接模具

[ContentProperty("Body")] 
public class SendScope : NativeActivity 
{ 
    [DefaultValue((string)null)] 
    [RequiredArgument] 
    public InArgument<string> Binding { get; set; } 

    [DefaultValue((string)null)] 
    [RequiredArgument] 
    public InArgument<string> Address { get; set; } 

    [Browsable(false)] 
    public Send Body { get; set; } 

    protected override void CacheMetadata(NativeActivityMetadata metadata) 
    { 
     if (this.Body == null || this.Body.EndpointAddress != null) 
     { 
      metadata.AddValidationError("Error ..."); 
      return; 
     } 
     this.Body.Endpoint = new Endpoint() 
     { 
      AddressUri = new Uri("http://localhost/"), 
      Binding = new BasicHttpBinding(), 
      ServiceContractName = this.Body.ServiceContractName 
     }; 
     metadata.AddChild(this.Body); 
     base.CacheMetadata(metadata); 
    } 

    protected override void Execute(NativeActivityContext context) 
    { 
     this.Body.Endpoint.Binding = GetBinding(this.Binding.Get(context)); 
     this.Body.Endpoint.AddressUri = new Uri(this.Address.Get(context)); 
     context.ScheduleActivity(Body); 
    } 


    private System.ServiceModel.Channels.Binding GetBinding(string binding) 
    { 
     if (binding == "basicHttpBinding") 
      return new BasicHttpBinding(); 
     //else ... others bindings 
     return null; 
    } 
} 

public class SendScopeFactory : IActivityTemplateFactory 
{ 
    public Activity Create(DependencyObject target) 
    { 
     return new SendScope() 
     { 
      DisplayName = "SendScope", 
      Body = new Send() 
      { 
       Action = "*", 
       OperationName = "ProcessMessage", 
       ServiceContractName = "IGenericContract", 
      } 
     }; 
    } 
} 
  1. 根据您的属性,如绑定,地址,安全等
  2. 在运行时设置Send.Endpoint属性创建自定义本地创建活动设计师为这个SendScope活动的东西simular像CorrelationScope
  3. 创建SendScopeFactory - 见上面的代码片断。
+0

我正在执行一个Workflow的实例,如下所示: 'Activity workflow1 = new Workflow1(); Task.WaitAll( Task.Run(()=> WorkflowInvoker.Invoke(workflow1)), Task.Run(()=> WorkflowInvoker.Invoke(workflow1)));' 尽管在'CacheMetadata'断点只击中一次。 – yuramag