欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

堅(jiān)持學(xué)習(xí)WF(14):自定義持久化服務(wù)

系統(tǒng) 1793 0

[置頂]堅(jiān)持學(xué)習(xí)WF文章索引

我們除了使用WF提供的SqlWorkflowPersistenceService外,還可以自定義持久化服務(wù)。因?yàn)橛械臅r(shí)候你可能不想使用Sql Server數(shù)據(jù)庫(kù),我們就可以通過(guò)自定義持久化服務(wù)來(lái)使用其他的數(shù)據(jù)庫(kù),文件等來(lái)進(jìn)行持久化存儲(chǔ)。

一:1.1 我們先看一個(gè)MSDN中的例子,當(dāng)從內(nèi)存中卸載工作流時(shí),工作流運(yùn)行時(shí)可使用該服務(wù)將工作流實(shí)例狀態(tài)保存到文件。該持久服務(wù)類代碼如下FilePersistence.cs:
??? public class FilePersistenceService : WorkflowPersistenceService
??? {
??????? public readonly static TimeSpan MaxInterval = new TimeSpan(30, 0, 0, 0);

??????? private bool unloadOnIdle = false ;
??????? private Dictionary<Guid,Timer> instanceTimers;

??????? public FilePersistenceService( bool unloadOnIdle)
??????? {
??????????? this .unloadOnIdle = unloadOnIdle;
??????????? this .instanceTimers = new Dictionary<Guid, Timer>();
??????? }

??????? protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock)
??????? {
??????????? // Save the workflow
??????????? Guid contextGuid = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty);
??????????? Console.WriteLine(" Saving instance: {0}\n ", contextGuid);
??????????? SerializeToFile( WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity), contextGuid);

??????????? // See when the next timer (Delay activity) for this workflow will expire
??????????? TimerEventSubscriptionCollection timers = (TimerEventSubscriptionCollection)rootActivity.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty);
??????????? TimerEventSubscription subscription = timers.Peek();
??????????? if (subscription != null )
??????????? {
??????????????? // Set a system timer to automatically reload this workflow when its next timer expires
??????????????? TimerCallback callback = new TimerCallback(ReloadWorkflow);
??????????????? TimeSpan timeDifference = subscription.ExpiresAt - DateTime.UtcNow;
??????????????? // check to make sure timeDifference is in legal range
??????????????? if (timeDifference > FilePersistenceService.MaxInterval)
??????????????? {
??????????????????? timeDifference = FilePersistenceService.MaxInterval;
??????????????? }
??????????????? else if (timeDifference < TimeSpan.Zero)
??????????????? {
??????????????????? timeDifference = TimeSpan.Zero;
??????????????? }
??????????????? this .instanceTimers.Add(contextGuid, new System.Threading.Timer(
??????????????????? callback,
??????????????????? subscription.WorkflowInstanceId,
??????????????????? timeDifference,
??????????????????? new TimeSpan(-1)));
??????????? }
??????? }

??????? private void ReloadWorkflow( object id)
??????? {
??????????? // Reload the workflow so that it will continue processing
??????????? Timer toDispose;
??????????? if ( this .instanceTimers.TryGetValue((Guid)id, out toDispose))
??????????? {
??????????????? this .instanceTimers.Remove((Guid)id);
??????????????? toDispose.Dispose();
??????????? }
??????????? this .Runtime.GetWorkflow((Guid)id);
??????? }

??????? // Load workflow instance state.
??????? protected override Activity LoadWorkflowInstanceState(Guid instanceId)
??????? {
??????????? Console.WriteLine(" Loading instance: {0}\n ", instanceId);
??????????? byte [] workflowBytes = DeserializeFromFile(instanceId);
??????????? return WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, null );
??????? }

??????? // Unlock the workflow instance state.
??????? // Instance state locking is necessary when multiple runtimes share instance persistence store
??????? protected override void UnlockWorkflowInstanceState(Activity state)
??????? {
??????????? //File locking is not supported in this sample
??????? }

??????? // Save the completed activity state.
??????? protected override void SaveCompletedContextActivity(Activity activity)
??????? {
??????????? Guid contextGuid = (Guid)activity.GetValue(Activity.ActivityContextGuidProperty);
??????????? Console.WriteLine(" Saving completed activity context: {0} ", contextGuid);
??????????? SerializeToFile(
??????????????? WorkflowPersistenceService.GetDefaultSerializedForm(activity), contextGuid);
??????? }

??????? // Load the completed activity state.
??????? protected override Activity LoadCompletedContextActivity(Guid activityId, Activity outerActivity)
??????? {
??????????? Console.WriteLine(" Loading completed activity context: {0} ", activityId);
??????????? byte [] workflowBytes = DeserializeFromFile(activityId);
??????????? Activity deserializedActivities = WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, outerActivity);
??????????? return deserializedActivities;

??????? }

??????? protected override bool UnloadOnIdle(Activity activity)
??????? {
??????????? return unloadOnIdle;
??????? }
??????? // Serialize the activity instance state to file
??????? private void SerializeToFile( byte [] workflowBytes, Guid id)
??????? {
??????????? String filename = id.ToString();
??????????? FileStream fileStream = null ;
??????????? try
??????????? {
??????????????? if (File.Exists(filename))
??????????????????? File.Delete(filename);

??????????????? fileStream = new FileStream(filename, FileMode.CreateNew, FileAccess.Write, FileShare.None);

??????????????? // Get the serialized form
??????????????? fileStream.Write(workflowBytes, 0, workflowBytes.Length);
??????????? }
??????????? finally
??????????? {
??????????????? if (fileStream != null )
??????????????????? fileStream.Close();
??????????? }
??????? }
??????? // Deserialize the instance state from the file given the instance id
??????? private byte [] DeserializeFromFile(Guid id)
??????? {
??????????? String filename = id.ToString();
??????????? FileStream fileStream = null ;
??????????? try
??????????? {
??????????????? // File opened for shared reads but no writes by anyone
??????????????? fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
??????????????? fileStream.Seek(0, SeekOrigin.Begin);
??????????????? byte [] workflowBytes = new byte [fileStream.Length];

??????????????? // Get the serialized form
??????????????? fileStream.Read(workflowBytes, 0, workflowBytes.Length);

??????????????? return workflowBytes;
??????????? }
??????????? finally
??????????? {
??????????????? fileStream.Close();
??????????? }
??????? }
??? }

1.2 看看我們的工作流設(shè)計(jì),只需要放入一個(gè)DelayActivity即可并設(shè)置他的Timeout時(shí)間,如下圖:

1.3 宿主程序加載了我們自定義的持久化服務(wù)后,執(zhí)行結(jié)果如下:

二:上面的例子其實(shí)很簡(jiǎn)單,我們只是做了一些基本的操作,還有很多工作沒有做。我們就來(lái)說(shuō)說(shuō)如何自定義持久化服務(wù)。自定義持久化服務(wù)大概有以下幾步:

1.定義自己的持久化類FilePersistenceService ,必須繼承自WorkflowPersistenceService.
2.實(shí)現(xiàn)WorkflowPersistenceService中所有的抽象方法,下面會(huì)具體介紹。
3.把自定義的持久化服務(wù)裝載到工作流引擎中(和裝載WF提供的標(biāo)準(zhǔn)服務(wù)的方式一樣)。

下面我們來(lái)介紹下WorkflowPersistenceService類中相關(guān)的抽象方法:

2.1 SaveWorkflowInstanceState: 將工作流實(shí)例狀態(tài)保存到數(shù)據(jù)存儲(chǔ)區(qū)。

    
      protected
    
    
      internal
    
    
      abstract
    
    
      void
    
     SaveWorkflowInstanceState(Activity rootActivity,
    
      bool
    
     unlock)
  
    rootActivity:工作流實(shí)例的根 Activity。
    
unlock:如果工作流實(shí)例不應(yīng)鎖定,則為 true;如果工作流實(shí)例應(yīng)該鎖定,則為 false。 關(guān)于鎖方面的我們暫時(shí)不提。
    ?
  
    在這個(gè)方法中我們會(huì)把rootActivity 序列化到 Stream 中,可以看我們上面的例子中的代碼實(shí)現(xiàn)的該方法中有這樣一段
  
    ?
  
    SerializeToFile( WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity), contextGuid);
    
private void SerializeToFile( byte [] workflowBytes, Guid id)
    ?
  
    SerializeToFile方法的第一個(gè)參數(shù)是需要一個(gè)byte[]的數(shù)組,我們是使用WorkflowPersistenceService.GetDefaultSerializedForm
    
(rootActivity)來(lái)實(shí)現(xiàn)的,那我們Reflector一下WorkflowPersistenceService這個(gè)類中的GetDefaultSerializedForm
方法,代碼如下:
    
      protected
    
    
      static
    
    
      byte
    
    [] GetDefaultSerializedForm(Activity activity)
    {
        DateTime now = DateTime.Now;
        
    
      using
    
     (MemoryStream stream = 
    
      new
    
     MemoryStream(0x2800))
        {
            stream.Position = 0L;
            activity.Save(stream);
            
    
      using
    
     (MemoryStream stream2 = 
    
      new
    
     MemoryStream((
    
      int
    
    ) stream.Length))
            {
                
    
      using
    
     (GZipStream stream3 = 
    
      new
    
     GZipStream(stream2, CompressionMode.Compress,
    
true )) { stream3.Write(stream.GetBuffer(), 0, ( int ) stream.Length); } ActivityExecutionContextInfo info = (ActivityExecutionContextInfo)
activity.GetValue(Activity.ActivityExecutionContextInfoProperty); TimeSpan span = (TimeSpan) (DateTime.Now - now); WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, " Serialized a
{0} with id {1} to length {2}. Took {3}.
", new object [] { info, info.ContextGuid,
stream2.Length, span }); byte [] array = stream2.GetBuffer(); Array.Resize< byte >( ref array, Convert.ToInt32(stream2.Length)); return array; } } }

可以看出主要是調(diào)用了activity.Save(stream); ,將rootActivity 序列化到 Stream 中,如果我們自定義這個(gè)方法我們要調(diào)用 Activity的save方法將Activity序列化到stream中去,我們?cè)趯?shí)現(xiàn)LoadWorkflowInstanceState方法時(shí)會(huì)調(diào)用Activity的Load方法來(lái)讀取,另外我們把工作流保存到持久化存儲(chǔ)里我們一般都使用WorkflowInstanceId來(lái)做為唯一性標(biāo)識(shí)

當(dāng)工作流實(shí)例完成或終止時(shí),工作流運(yùn)行時(shí)引擎最后一次調(diào)用 SaveWorkflowInstanceState。因此,如果 GetWorkflowStatus等于 Completed或 Terminated,則可以從數(shù)據(jù)存儲(chǔ)區(qū)中安全地刪除工作流實(shí)例及其所有關(guān)聯(lián)的已完成作用域。此外,可以訂閱 WorkflowCompleted或 WorkflowTerminated事件,確定何時(shí)可以安全地刪除與工作流實(shí)例關(guān)聯(lián)的記錄。是否確實(shí)從數(shù)據(jù)存儲(chǔ)區(qū)中刪除記錄取決于您的實(shí)現(xiàn)。

如果無(wú)法將工作流實(shí)例狀態(tài)保存到數(shù)據(jù)存儲(chǔ)區(qū),則應(yīng)引發(fā)帶有適當(dāng)錯(cuò)誤消息的 PersistenceException。

? 2.2 LoadWorkflowInstanceState : SaveWorkflowInstanceState 中保存的工作流實(shí)例的指定狀態(tài)加載回內(nèi)存

    
      protected
    
    
      internal
    
    
      abstract
    
     Activity LoadWorkflowInstanceState(Guid instanceId)
  
instanceId:工作流實(shí)例的根活動(dòng)的 Guid。

必須還原活動(dòng)的相同副本。為此,必須從數(shù)據(jù)存儲(chǔ)區(qū)中工作流實(shí)例的表示形式中還原有效的 Stream;然后,必須將此 Stream 傳遞到重載的 Load 方法之一,用于反序列化工作流實(shí)例。如果持久性服務(wù)無(wú)法從其數(shù)據(jù)存儲(chǔ)區(qū)加載工作流實(shí)例狀態(tài),則它應(yīng)引發(fā)帶有適當(dāng)消息的 PersistenceException。

在我們上面例子中實(shí)現(xiàn)的該方法中,

    
      protected
    
    
      override
    
     Activity LoadWorkflowInstanceState(Guid instanceId) 
{ 
    Console.WriteLine("
    
      Loading instance: {0}\n
    
    ", instanceId); 
    
    
      byte
    
    [] workflowBytes = DeserializeFromFile(instanceId); 
    
    
      return
    
     WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, 
    
      null
    
    ); 
}
  

我們調(diào)用了WorkflowPersistenceService.RestoreFromDefaultSerializedForm(workflowBytes, null);方法
我們Reflector出WorkflowPersistenceService類的代碼后可以看到,如下代碼:

protected static Activity RestoreFromDefaultSerializedForm( byte [] activityBytes, Activity outerActivity)
??? {
??????? Activity activity;
??????? DateTime now = DateTime.Now;
??????? MemoryStream stream = new MemoryStream(activityBytes);
??????? stream.Position = 0L;
??????? using (GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress, true ))
??????? {
??????????? activity = Activity.Load(stream2, outerActivity);
??????? }
??????? TimeSpan span = (TimeSpan) (DateTime.Now - now);
??????? WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, " Deserialized a {0}
??????????????????????????????????????????????????? to length {1}. Took {2}.
", new object [] { activity, stream.Length, span });
??????? return activity;
??? }

    這段代碼核心的調(diào)用了Activity.Load方法將從 Stream 加載 Activity的實(shí)例。
  
    
      2.3 SaveCompletedContextActivity
    
  
    
      protected
    
    
      internal
    
    
      abstract
    
    
      void
    
     SaveCompletedContextActivity(Activity activity)
  
    activity:表示已完成范圍的 Activity。
  
    ?
  

將指定的已完成作用域保存到數(shù)據(jù)存儲(chǔ)區(qū)。保存完成活動(dòng)的AEC環(huán)境以便實(shí)現(xiàn)補(bǔ)償,比如WhileActivity他每次循環(huán)的
都會(huì)創(chuàng)建新的AEC環(huán)境,這個(gè)時(shí)候完成的活動(dòng)的AEC就會(huì)被保存,但是前提是這個(gè)活動(dòng)要支持補(bǔ)償才可以,所有如果你的WhileActivity里包含SequenceActivity這樣該方法是不會(huì)被調(diào)用的,如果你換成CompensatableSequenceActivity就可以了

工作流運(yùn)行時(shí)引擎保存已完成作用域活動(dòng)的狀態(tài),以便實(shí)現(xiàn)補(bǔ)償。必須調(diào)用重載的 Save 方法之一,將 activity 序列化到 Stream 中;然后可以選擇在將 Stream 寫入到數(shù)據(jù)存儲(chǔ)區(qū)之前,對(duì)其執(zhí)行其他處理。但是,在工作流運(yùn)行時(shí)引擎調(diào)用 LoadCompletedContextActivity時(shí),必須還原活動(dòng)的相同副本。

本例子的程序中不會(huì)涉及到這部分

也同樣使用了WorkflowPersistenceService的GetDefaultSerializedForm方法

2.4 LoadCompletedContextActivity?

和SaveCompletedContextActivity是對(duì)應(yīng)的,加載SaveCompletedContextActivity中保存的已完成活動(dòng)的AEC,就不多說(shuō)了

2.5 UnlockWorkflowInstanceState: 解除對(duì)工作流實(shí)例狀態(tài)的鎖定。

此方法是抽象的,因此它不包含對(duì)鎖定和解鎖的默認(rèn)實(shí)現(xiàn)。

實(shí)現(xiàn)自定義持久性服務(wù)時(shí),如果要實(shí)現(xiàn)鎖定方案,則需要重寫此方法,并在 SaveWorkflowInstanceState方法中提供根據(jù)解鎖參數(shù)的值進(jìn)行鎖定-解鎖的機(jī)制。

比如我們的工作流在取消的時(shí)候,這個(gè)方法被調(diào)用來(lái)解除工作流實(shí)例狀態(tài)的鎖定。

2.6 UnloadOnIdle

返回一個(gè)布爾值,確定在工作流空閑時(shí)是否將其卸載。

這些都只是自定義持久化中最基本的,就先說(shuō)這些吧。

堅(jiān)持學(xué)習(xí)WF(14):自定義持久化服務(wù)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 久久91精品国产91久久小草 | 久久精品人人做人人看最新章 | 久久激情五月丁香伊人 | 欧美一区二 | 国精品人妻无码一区二区三区性色 | 国产麻豆剧传媒精品好看的片 | 国产亚洲精品精品国产亚洲综合 | 成人性生活视频在线播放 | 色妇影院| xxnxx中国18| 久久综合九九 | 亚洲综合综合在线 | 婷婷久久五月天 | 久久综合九九 | 亚洲AV久久无码精品九号 | 午夜小电影 | 精品日本一区二区 | 欧美成人18| 国产一国产一有一级毛片 | 国产精品免费av | 九九视频这里只有精品99 | 亚洲高清视频在线 | 日韩国产成人资源精品视频 | 亚洲情乱 | 一区二区三区四区免费看 | 欧美网站在线看 | 欧美国产一区二区三区 | 免费午夜电影 | 青青草99热久久 | 九九久久久 | 国产大片在线观看 | 成人综合久久综合 | 另类二区三四 | 国产视频99| 美女视频一区 | 99久久国产综合精品女小说 | 夜夜久久| 日韩免费视频一区二区 | 免费看一级毛片 | 色婷婷色综合缴情在线 | 精品国产影院 |