2

トランザクションスコープを使用した非同期キャッシュおよびデータベースの更新は次のとおりです。 v 4.5.1で導入されたTransactionScopeAsyncFlowOption.Enabledを使用することはできません。これは、使用しているApache Ignite.Netキャッシュがサポートしていないためです。私は明示的にトランザクションを完了するために、Synchronization Context Sendメソッドを使用して、現在のSynchronization Contextをキャプチャしてことで、回避策を見つけることを試みたが、私はまだエラーTransaction scope must be disposed on same thread it was createdTransactionScopeAsyncFlowOption.Enabledを使用しないAsync TransactionScopeの有効化

Async Updateを達成することについて移動する方法を任意の提案を取得するので、これは動作しません。アパッチのIgniteのサポートにより、提案の一つのようなものを使用することです。そのため、最良の選択肢ブログ全体検索のかなりの量の後

public async Task Update() 
{ 
    // Capture Current Synchronization Context 
    var sc = SynchronizationContext.Current; 

    TransactionOptions tranOptions = new TransactionOptions(); 
    tranOptions.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead; 


    using (var ts = new TransactionScope()) 
    { 
     // Do Cache Update Operation as Async 
     Task cacheUpdate = // Update Cache Async 

     // Do Database Update Operation as Async 
     Task databaseUpdate = // Update Database Async 

     await Task.WhenAll(cacheUpdate, databaseUpdate); 

       sc.Send(new SendOrPostCallback(
       o => 
       { 
        ts.Complete(); 
       }), sc);   
    } 
} 
+3

で実行する非同期メソッドを取得するTransactionScopeAsyncFlowOption.Enabledは必要ありません。 .NET 4.0で実行する必要がありますか? – Evk

+0

これは、Javaプロセスと通信するApache Ignite.Netによって公開されるCache Update Asyncメソッドを使用します。これらのメソッドは、このオプションをサポートしていません。なぜ私はすべての内部の詳細を認識していません –

+2

この機能は、サードパーティのコンポーネントからの明示的なサポートが必要であることを知らなかった。 – Evk

答えて

1

の一つではない

Task.WhenAll(cacheUpdate, databaseUpdate).Wait()を、それは非同期コード同期になるだろうし、記事では、Stephen Toubの次のブログが、同じスレッド上でAsyncメソッドの継続を実現するのに役立ち、トランザクションスコープの問題を回避しています。今、私はあなたがTransactionScopeAsyncFlowOption.Enabledを使用することはできませんなぜ私は非常に取得していないTransactionScope

https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/

void Main() 
{ 
    // Modified Async Scheduler for Continuations to work on Exactly same thread 
    // Required in the case same Thread is required for Task Continuation post await 
    Run(async() => await DemoAsync()); 

    "Main Complete".Dump(); 
} 

static async Task DemoAsync() 
{ 
    // Transcation Scope test (shall dispose 
    using (var ts = new TransactionScope()) 
    {    
     await Cache + Database Async update 
     ts.Complete(); 
     "Transaction Scope Complete".Dump(); 
    } 
} 

// Run Method to utilize the Single Thread Synchronization context, thus ensuring we can 
// Control the threads/Synchronization context post await, cotinuation run of specific set of threads 

public static void Run(Func<Task> func) 
{ 
    // Fetch Current Synchronization context 
    var prevCtx = SynchronizationContext.Current; 

    try 
    { 
     // Create SingleThreadSynchronizationContext 
     var syncCtx = new SingleThreadSynchronizationContext(); 

     // Set SingleThreadSynchronizationContext 
     SynchronizationContext.SetSynchronizationContext(syncCtx); 

     // Execute Func<Task> to fetch the task to be executed 
     var t = func(); 

     // On Continuation complete the SingleThreadSynchronizationContext 
     t.ContinueWith(
      delegate { syncCtx.Complete(); }, TaskScheduler.Default); 

     // Ensure that SingleThreadSynchronizationContext run on a single thread 
     // Execute a Task and its continuation on same thread 
     syncCtx.RunOnCurrentThread(); 

     // Fetch Result if any 
     t.GetAwaiter().GetResult(); 
    } 
    // Reset the Previous Synchronization Context 
    finally { SynchronizationContext.SetSynchronizationContext(prevCtx); } 
} 

// Overriden Synchronization context, using Blocking Collection Consumer/Producer model 
// Ensure that same Synchronization context/Thread/set of threads are maintained 
// In this case we main a single thread for continuation post await 

private sealed class SingleThreadSynchronizationContext : SynchronizationContext 
{ 
    // BlockingCollection Consumer Producer Model 
    private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> 
     m_queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>(); 

    // Override Post, which is called during Async continuation 
    // Send is for Synchronous continuation 
    public override void Post(SendOrPostCallback d, object state) 
    { 
     m_queue.Add(
      new KeyValuePair<SendOrPostCallback, object>(d, state)); 
    } 

    // RunOnCurrentThread, does the job if fetching object from BlockingCollection and execute it 
    public void RunOnCurrentThread() 
    { 
     KeyValuePair<SendOrPostCallback, object> workItem; 
     while (m_queue.TryTake(out workItem, Timeout.Infinite)) 
      workItem.Key(workItem.Value); 
    } 

    // Compete the SynchronizationContext 
    public void Complete() { m_queue.CompleteAdding(); } 
} 
関連する問題