1

私が作成したNativeActivity派生アクティビティは、ブックマークをピック ブランチのトリガーとして使用するものです。MSDN で見つけたものを使用して、これを書いてブランチをトリガーしようとしました。ブランチには、send アクティビティを介してリモート クライアントへのサービス コールバックを起動するアクティビティが含まれています。トリガーに遅延を設定すると、コールバックがクライアントに対して正常に起動します。コード アクティビティを使用すると、分岐選択アクティビティが起動しません。

public sealed class UpdateListener : NativeActivity<ClientUpdate>
{
    [RequiredArgument]
    public InArgument<string>     BookmarkName { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        context.CreateBookmark(BookmarkName.Get(context),
                    new BookmarkCallback(this.OnResumeBookmark));
    }


    protected override bool CanInduceIdle
    {
        get { return true; }
    }


    public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj )
    {
        Result.Set(context, (ClientUpdate)obj);
    }
}

そのため、将来のブックマーク参照がトリガーを実行するためのブックマーク名を設定するには、引数が必要です。OnResumeBookmark() はClientUpdate、workflowapp をホストしているアプリケーションから渡されたオブジェクトを受け取ります。ClientUpdateこのアクティビティは、オブジェクトをワークフローに渡して pick ブランチの send アクティビティを介してリモート クライアントに送信できるようにオブジェクトを返すことです。とにかく理論的には。

何らかの理由で、それは正しいように見えますが、間違っているように感じます。WF サービスに必要なものを処理するために別の方法でアクティビティを作成する必要があるかどうかはわかりません。

4

2 に答える 2

1

ここでアクションを実行する拡張機能 (IWorkflowInstanceExtension を実装する) を作成すると、意図が少し明確になると思います。

例えば:

public sealed class AsyncWorkExtension 
    : IWorkflowInstanceExtension
{
    // only one extension per workflow
    private WorkflowInstanceProxy _proxy;
    private Bookmark _lastBookmark;

    /// <summary>
    /// Request the extension does some work for an activity
    /// during which the activity will idle the workflow
    /// </summary>
    /// <param name="toResumeMe"></param>
    public void DoWork(Bookmark toResumeMe)
    {
        _lastBookmark = toResumeMe;
        // imagine I kick off some async op here
        // when complete system calls WorkCompleted below
        // NOTE:  you CANNOT block here or you block the WF!
    }

    /// <summary>
    /// Called by the system when long-running work is complete
    /// </summary>
    /// <param name="result"></param>
    internal void WorkCompleted(object result)
    {
        //NOT good practice!  example only
        //this leaks resources search APM for details
        _proxy.BeginResumeBookmark(_lastBookmark, result, null, null);
    }

    /// <summary>
    /// When implemented, returns any additional extensions 
    /// the implementing class requires.
    /// </summary>
    /// <returns>
    /// A collection of additional workflow extensions.
    /// </returns>
    IEnumerable<object> IWorkflowInstanceExtension
        .GetAdditionalExtensions()
    {
        return new object[0];
    }

    /// <summary>
    /// Sets the specified target 
    /// <see cref="WorkflowInstanceProxy"/>.
    /// </summary>
    /// <param name="instance">The target workflow instance to set.</param>
    void IWorkflowInstanceExtension
        .SetInstance(WorkflowInstanceProxy instance)
    {
        _proxy = instance;
    }
}

アクティビティ内では、次のように使用します。

 var ext = context.GetExtension<AsyncWorkExtension>();
 var bookmark = context.CreateBookmark(BookmarkCallback);
 ext.DoWork(bookmark);
 return;

この方法は (「外部」の世界に意味を伝えるためにブックマーク名を使用する代わりに) はるかに明示的であり、たとえば、ブックマーク名よりも多くの情報を送信する必要がある場合に拡張するのがはるかに簡単です。

于 2010-07-22T16:37:30.747 に答える
0

ここで実際にブックマークを再開するものはありますか? そうでない場合、ワークフローは非常に辛抱強く待機し、何も起こりません。

于 2010-07-01T19:44:29.910 に答える