2011-09-28 4 views
2

먼저 면책 조항 - 나는 WF 새로운 오전과 나는 단지 3 일 WF4와 함께 연주 beel했습니다 - 내가 가질 수있는 양성 또는 절름발이 질문에 대한 사과 ... 그래서머신 (StateMachine) WF4에서

내가하려고 프로젝트에 WF4 State Machine을 구현하십시오. 여기에 몇 가지 배경 정보입니다 :

  1. 나는 내가 네트워크 스택
  2. 로부터 이벤트를 수신 DLL로 인터페이스 층이 네트워킹 스택
  3. 에 다른 명령을 생성 할 수있는 주요 애플 리케이션으로의 WinForm UI를 상태 머신은 인터페이스 계층에 평행 한 중간 계층의 어딘가에 소프트 폰 상태 머신을 구현해야합니다. 전화 상태는 네트워킹 이벤트 및 사용자 작업에 따라 변경됩니다. 일부 사용자 동작은 네트워킹 명령을 유발하고 일부는 상태 시스템에 직접 영향을 줄 수 있습니다.
  4. 내 인터페이스 레이어는 객체 전화를 구현하므로이 객체를 상태 시스템의 호스트로 만들었습니다. 나는 (다른 네임 스페이스 WinSipNetLib에 WinSipItf 개체 생활) 다음 전화 개체에 내 주요 인터페이스 객체 WinSipItf를 전달하고, 할 수 있어요 :

코드 :

public void Initialize(WinSipNetLib.WinSipItf winSipItf, string hostname, string user, string password) 
{ 
    try 
    { 
     WinSipItf = winSipItf; 
     var Itf = WinSipItf; 
     var input = new Dictionary<string, object> 
        { 
         {"winSipItf", Itf} 
        }; 
     this.WorkFlowHostApp = new WorkflowApplication(new Activity1(), input) 
     { 
      Idle = this.OnWorkflowIdle, 
      Completed = this.OnWorkflowCompleted 
     }; 

     // Setup the Tracking to output in the debug window 
     WorkFlowHostApp.Extensions.Add(new Tracker()); 

     this.WorkFlowHostApp.Extensions.Add(this); 

     this.workflowBusy.Reset(); 

     Console.WriteLine("Starting Workflow"); 
     this.WorkFlowHostApp.Run(); 
    } 
    catch (Exception ex) 
    { 
     Console.Write(ex); 
    } 
} 

전화 초기 상태는 초기이며이 대상 상태 PhoneIdle이있는 자동/널 트리거. OnEntrace to Initial 상태 네트워킹 스택에 전화 등록을 몇 개 실행해야합니다. 콜백을 등록 (동기화 작업)하고 네트워크 스택 관리자 (async)에 등록해야합니다. 이 모든 기능은 내 인터페이스 계층에 구성된 API를 통해 액세스하는 낮은 수준의 관리되지 않는 코드에서 작동합니다. 성공적으로 등록되면 인터페이스 레이어에서 콜백을 받고 이벤트를 시작합니다. 따라서 내 등록 Acitivity은 다음과 같습니다

public sealed class Register : NativeActivity<Int32> 
{ 
    // Define an activity input argument of type string 
    [RequiredArgument] 
    public InArgument<WinSipNetLib.WinSipItf> winSipItf { get; set; } 

    #region Constants and Fields 

    private readonly Variable<NoPersistHandle> _noPersistHandle = new Variable<NoPersistHandle>(); 
    internal const string BookmarkName = "WaitingForAccountStatusEvent"; 

    /// <summary> 
    /// The transition callback. 
    /// </summary> 
    private BookmarkCallback registrationCallback; 

    #endregion 

    #region Properties 

    ///// <summary> 
    ///// Gets or sets PhoneTransition. 
    ///// </summary> 
    //public PhoneTransition PhoneTransition { get; set; } 

    /// <summary> 
    /// Gets a value indicating whether CanInduceIdle. 
    /// </summary> 
    protected override bool CanInduceIdle 
    { 
     get 
     { 
      return true; 
     } 
    } 

    /// <summary> 
    /// Gets TransitionCallback. 
    /// </summary> 
    private BookmarkCallback RegistrationCallback 
    { 
     get 
     { 
      return this.registrationCallback ?? (this.registrationCallback = new BookmarkCallback(this.OnRegistrationCallback)); 
     } 
    } 

    #endregion 

    #region Methods 

    /// <summary> 
    /// The cache metadata. 
    /// </summary> 
    /// <param name="metadata"> 
    /// The metadata. 
    /// </param> 
    protected override void CacheMetadata(NativeActivityMetadata metadata) 
    { 
     metadata.RequireExtension(typeof(Tracker)); 
     metadata.RequireExtension(typeof(Phone)); 
     metadata.RequireExtension(typeof(WaitForRegistrationExt)); 
     // !!! and one more for GUI 

     // Provide a Func<T> to create the extension if it does not already exist 
     metadata.AddDefaultExtensionProvider(() => new WaitForRegistrationExt()); 

     metadata.AddArgument(new RuntimeArgument("winSipItf", typeof(WinSipNetLib.WinSipItf), ArgumentDirection.In, true)); 
     metadata.AddArgument(new RuntimeArgument("Result", typeof(int), ArgumentDirection.Out, false)); 

     metadata.AddImplementationVariable(_noPersistHandle); 
    } 

    protected override void Execute(NativeActivityContext context) 
    { 
     // Enter a no persist zone to pin this activity to memory since we are setting up a delegate to receive a callback 
     var handle = _noPersistHandle.Get(context); 
     handle.Enter(context); 

     // Get Phone extension needed to call the functions in WinSipItf 
     Phone phone = (Phone)context.GetExtension<Phone>(); 

     // Get (which may create) the extension 
     WaitForRegistrationExt regExt = context.GetExtension<WaitForRegistrationExt>(); 

     // Add the callback 
     regExt.AddRegistrationCallback(winSipItf.Get(context)); 

     bool bRet = phone.WinSipItf.RegisterDBusCallback("WinSipPhone"); 

     // Obtain the runtime value of the Text input argument 
     if (bRet == false) 
     { 
      this.Result.Set(context, bRet.ToString()); 
      return; 
     } 

     string hostname = "demo2.demo.com"; 
     string username = "406"; 
     string password = "123123"; 
     string id = username + "@" + hostname; 
     String regUri = hostname; 
     if (phone.WinSipItf.DoSipRegister(id, regUri, username, password) == 0) 
     { 
      this.Result.Set(context, bRet.ToString()); 
      return; 
     } 

     // Set a bookmark - the extension will resume when the Gizmo is fired 
     context.CreateBookmark(BookmarkName, RegistrationCallback); 

     //context.CreateBookmark(this.PhoneTransition.ToString(), this.RegistrationCallback); 

     //// Obtain the runtime value of the Text input argument 
     //string text = context.GetValue(this.Text); 

     //Result.Set(context, string.Format("The text is {0}", text)); 
    } 

    /// <summary> 
    /// The on transition callback. 
    /// </summary> 
    /// <param name="context"> 
    /// The context. 
    /// </param> 
    /// <param name="bookmark"> 
    /// The bookmark. 
    /// </param> 
    /// <param name="value"> 
    /// The value. 
    /// </param> 
    /// <exception cref="InvalidOperationException"> 
    /// </exception> 
    private void OnRegistrationCallback(NativeActivityContext context, Bookmark bookmark, object value) 
    { 
     if (value is WinSipItf.MSGDATA) 
     { 

     } 
     ////if (value is StateTransitionResult) 
     //{ 
     // this.Result.Set(context, value as StateTransitionResult); 
     //} 
     //else if (value != null) 
     //{ 
     // // Resumed with something else 
     // throw new InvalidOperationException(
     //  "You must resume PhoneTransition bookmarks with a result of type StateTransitionResult"); 
     //} 

     // Exit the no persist zone 
     var handle = _noPersistHandle.Get(context); 
     handle.Exit(context); 
    } 

    #endregion 
} 

당신은 내가 좋아하는 CAL을 만드는 코드에서 볼 수 있듯이 : phone.WinSipItf.DoSipRegister 이 유효인가를? 나는 모든 상태 머신이 WinSipItf 객체가 생성 된 thread와는 다른 스레드에서 실행되고 있다고 생각한다. Redundant를 사용하면 여기에 아무 것도 없다. Execute 또는 CacheMetadata를 사용할 수 없다. 이 시점에서 무엇을해야할지 확신하지 못합니다. 내 xaml 다이어그램이 꽤 만들어 졌음을 알게 되겠지만이 사용자 지정 작업을 구성하여 Initial 상태와 Idle 상태로의 전환 만 구현하려고했습니다 ...

아마도 shouold는 간단한 질문부터 시작했습니다. "Initial state Entry"에 등록 활동을 삭제하면 "winSipItf '가 제공되지 않았습니다."라는 필수 활동 인수 값. 나는 모든 코드를 확인했는데 이유를 알지 못한다. 나는 무엇을 놓치고 있습니까?

답변

0

워크 플로 정의를 추가하지 않았지만 "winSipItf '가 제공되지 않았습니다."라는 필수 활동 인수 값이 "등록되지 않은 등록 활동에 대한 winSipItf 인수의 결과 인 것 같습니다. 그것은 워크 플로우에서 VB 표현식을 사용하여 설정해야하므로 필수로 표시됩니다. 워크 플로에 winSipItf라는 이름의 인수를 제공하고 있지만이 인수는 worklfow 인수에 연결되어 있으며 동일한 인수 이름을 가진 포함 된 활동으로 전파되지 않습니다.