Workflow foundation 4 服务总线工作流活动

Workflow foundation 4 服务总线工作流活动,workflow-foundation-4,async-await,c#-5.0,azure-servicebus-queues,Workflow Foundation 4,Async Await,C# 5.0,Azure Servicebus Queues,我想访问带有某些特定活动的工作流中的服务总线队列和主题 我找不到任何适合这种情况的(和)是最近的一个 我想设计一个自定义活动,它使用QueueClient异步接收代理消息,使用用async/await模式实现的BeginReceive方法(请参阅) 首先,我想问一下,是否有什么原因让我更喜欢建议的方法(适应的WCF)而不是我想要的方法(使用QueueClient) 然后,我将感谢您以一种持久性友好的方式帮助设计它 更新: 这就是我迄今为止所尝试的: public class AsyncRecei

我想访问带有某些特定活动的工作流中的服务总线队列和主题

我找不到任何适合这种情况的(和)是最近的一个

我想设计一个自定义活动,它使用QueueClient异步接收代理消息,使用用async/await模式实现的BeginReceive方法(请参阅)

首先,我想问一下,是否有什么原因让我更喜欢建议的方法(适应的WCF)而不是我想要的方法(使用QueueClient)

然后,我将感谢您以一种持久性友好的方式帮助设计它

更新:

这就是我迄今为止所尝试的:

public class AsyncReceiveBrokeredMessage : AsyncCodeActivity<BrokeredMessage>
{
    [RequiredArgument]
    public InArgument<string> ConnectionString { get; set; }

    [RequiredArgument]
    public InArgument<string> Path { get; set; }

    protected sealed override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        var connectionString = this.ConnectionString.Get(context);
        var path = this.Path.Get(context);
        var queueClient = QueueClient.CreateFromConnectionString(connectionString, path);
        var cts = new CancellationTokenSource();
        context.UserState = new ReceiveState
                                {
                                    CancellationTokenSource = cts,
                                    QueueClient = queueClient
                                };
        var task = ExecuteAsync(context, cts.Token);
        var tcs = new TaskCompletionSource<BrokeredMessage>(state);
        task.ContinueWith(
            t =>
                {
                    if (t.IsFaulted)
                    {
                        tcs.TrySetException(t.Exception.InnerExceptions);
                    }
                    else if (t.IsCanceled)
                    {
                        tcs.TrySetCanceled();
                    }
                    else
                    {
                        tcs.TrySetResult(t.Result);
                    }

                    if (callback != null)
                    {
                        callback(tcs.Task);
                    }
                });

        return tcs.Task;
    }

    protected sealed override BrokeredMessage EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
        var task = (Task<BrokeredMessage>)result;
        try
        {
            return task.Result;
        }
        catch (OperationCanceledException)
        {
            if (context.IsCancellationRequested)
            {
                context.MarkCanceled();
            }
            else
            {
                throw;
            }

            return null; // or throw?
        }
        catch (AggregateException exception)
        {
            if (exception.InnerException is OperationCanceledException)
            {
                if (context.IsCancellationRequested)
                {
                    context.MarkCanceled();
                }
                else
                {
                    throw;
                }

                return null; // or throw?
            }

            ExceptionDispatchInfo.Capture(exception.InnerException).Throw();
            throw;
        }
    }

    protected override void Cancel(AsyncCodeActivityContext context)
    {
        var state = (ReceiveState)context.UserState;
        state.CancellationTokenSource.Cancel();
    }

    private async Task<BrokeredMessage> ExecuteAsync(
        AsyncCodeActivityContext context, CancellationToken cancellationToken)
    {
        var receiveState = context.UserState as ReceiveState;
        var receiveTask = Task<BrokeredMessage>.Factory.FromAsync(
            receiveState.QueueClient.BeginReceive, receiveState.QueueClient.EndReceive, null);
        var completionTask = receiveTask.ContinueWith(
             t =>
                 {
                     BrokeredMessage result;
                     if (t.IsCanceled)
                     {
                         context.MarkCanceled();
                         result = null;
                     }
                     else if (t.IsFaulted)
                     {
                         result = null;
                     }
                     else
                     {

                         t.Result.Complete();
                         result = t.Result;
                     }

                     receiveState.QueueClient.Close();
                     return result;
                 },
             cancellationToken);
        return await completionTask;
    }

    private class ReceiveState
    {
        public CancellationTokenSource CancellationTokenSource { get; set; }

        public QueueClient QueueClient { get; set; }
    }
}
公共类AsyncReceiveBrokeredMessage:AsyncCodeActivity
{
[必需参数]
公共InArgument连接字符串{get;set;}
[必需参数]
公共非独占路径{get;set;}
受保护的密封重写IAsyncResult BeginExecute(AsyncCodeActivityContext上下文、AsyncCallback回调、对象状态)
{
var connectionString=this.connectionString.Get(上下文);
var path=this.path.Get(上下文);
var queueClient=queueClient.CreateFromConnectionString(connectionString,路径);
var cts=新的CancellationTokenSource();
context.UserState=新接收状态
{
CancellationTokenSource=cts,
QueueClient=QueueClient
};
var task=ExecuteAsync(上下文,cts.Token);
var tcs=新任务完成源(状态);
task.ContinueWith(
t=>
{
如果(t.IsFaulted)
{
tcs.TrySetException(t.Exception.InnerException);
}
否则,如果(t.IsCanceled)
{
tcs.trysetconceled();
}
其他的
{
tcs.TrySetResult(t.Result);
}
if(回调!=null)
{
回调(tcs.Task);
}
});
返回tcs.Task;
}
受保护的密封覆盖代理消息EndExecute(AsyncCodeActivityContext上下文,IAsyncResult结果)
{
var任务=(任务)结果;
尝试
{
返回任务。结果;
}
捕获(操作取消异常)
{
if(context.IsCancellationRequested)
{
MarkCanceled();
}
其他的
{
投掷;
}
返回null;//还是抛出?
}
捕获(AggregateException异常)
{
如果(exception.InnerException为OperationCanceledException)
{
if(context.IsCancellationRequested)
{
MarkCanceled();
}
其他的
{
投掷;
}
返回null;//还是抛出?
}
ExceptionDispatchInfo.Capture(exception.InnerException.Throw();
投掷;
}
}
受保护的覆盖无效取消(AsyncCodeActivityContext上下文)
{
var state=(ReceiveState)context.UserState;
state.CancellationTokenSource.Cancel();
}
专用异步任务ExecuteAsync(
AsyncCodeActivityContext上下文,CancellationToken CancellationToken)
{
var receiveState=context.UserState作为receiveState;
var receiveTask=Task.Factory.fromsync(
receiveState.QueueClient.BeginReceive,receiveState.QueueClient.EndReceive,null);
var completionTask=receiveTask.ContinueWith(
t=>
{
代理消息结果;
如果(t.IsCanceled)
{
MarkCanceled();
结果=空;
}
否则,如果(t.IsFaulted)
{
结果=空;
}
其他的
{
t、 Result.Complete();
结果=t.结果;
}
receiveState.QueueClient.Close();
返回结果;
},
取消令牌);
返回等待完成任务;
}
私有类接收状态
{
public CancellationTokenSource CancellationTokenSource{get;set;}
公共队列客户端{get;set;}
}
}
并以这种方式进行了测试(使用本地Windows Server服务总线):

var connectionString=新变量
{
默认值=connectionStringValue
};
变量路径=新变量
{
默认值=路径值
};
var测试=新的While
{
身体=
新选择
{
分支机构=
{
新PickBranch
{
触发=
新AsyncReceiveBrokeredMessage
{
ConnectionString=新的InArgument(ConnectionString),
var connectionString = new Variable<string>
                                   {
                                       Default = connectionStringValue
                                   };
        var path = new Variable<string>
                       {
                           Default = pathValue
                       };
        var test = new While
                       {
                           Body =
                               new Pick
                                   {
                                       Branches =
                                           {
                                               new PickBranch
                                                   {
                                                       Trigger =
                                                           new AsyncReceiveBrokeredMessage
                                                               {
                                                                   ConnectionString = new InArgument<string>(connectionString),
                                                                   Path = new InArgument<string>(path)
                                                               },
                                                       Action =
                                                           new WriteLine
                                                               {
                                                                   Text =
                                                                       "Received message"
                                                               }
                                                   },
                                               new PickBranch
                                                   {
                                                       Trigger =
                                                           new Delay
                                                               {
                                                                   Duration = TimeSpan.FromSeconds(10)
                                                               },
                                                       Action =
                                                           new WriteLine
                                                               {
                                                                   Text =
                                                                       "Timeout!"
                                                               }
                                                   }
                                           }
                                   },
                           Condition = true,
                           Variables = { connectionString, path }
                       };
        WorkflowInvoker.Invoke(test);
NamespaceManager.CreateSubscription(
        new SubscriptionDescription(TopicName, SubscriptionName)
            {
                LockDuration = TimeSpan.FromMinutes(5),
                DefaultMessageTimeToLive = TimeSpan.FromDays(7),
                EnableDeadLetteringOnMessageExpiration = true
            });