Syncronization of async EF Tasks

.net-4.5 async-await c# entity-framework-6 multithreading

Question

I'm developing an application that will manage company resources. We are using.Net 4.5 and EntityFramework 6.1.3 with an MS SQL database. Now, for instance, DbContext has async methods.

protected Task<int> SaveChangesAsync();

I am aware that DbContext is not thread-safe, therefore I won't be calling any async actions with the intention of having them run concurrently. But while I poll the database, I must free up my GUI thread.

The application is meant to be constantly updated, therefore you wouldn't typically program with await keywords and "just be carefull" not to call two Async activities at the same time. Consequently, we are connected to a server. Now, a polling command is delivered to all Applications that are currently working on this database whenever another user updates the database. This polling instruction could be executed at any moment, creating a race condition with any user-initiated async database polling.

I want to queue up each Task following the one before it. BUT I'm not sure how to accomplish it or even if it's a good idea. I have so far tried using Task. ContinueWith(), but I soon realized that my Tasks were never commencing, so I continued to wait interminably.

The current code is shown here.
(_lastRunningTask is initialized in the constructor of my DbContext inheriting class with the following declaration:

_lastRunningTask = Task.Run(() => { Thread.Sleep(1); });

)

private Task _lastRunningTask;

private Task<int> SaveChangesAsyncImpl(CancellationToken cancellationToken)
    {
        return ValidateEntitiesAsyncImpl().ContinueWith(p => SaveChangesAsync(cancellationToken)).Unwrap();
    }

    public override int SaveChanges()
    {

        Task<int> t = _lastRunningTask.ContinueWith(p => SaveChangesAsyncImpl(CancellationToken.None)).Unwrap();

        _lastRunningTask = t;

        return t.Result;
    }
    public override Task<int> SaveChangesAsync()
    {
        return SaveChangesAsync(CancellationToken.None);
    }
    public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
    {
        Task<int> t = _lastRunningTask.ContinueWith(p => SaveChangesAsyncImpl(cancellationToken)).Unwrap();
        _lastRunningTask = t;
        return t;
    }




    public Task ValidateEntitiesAsync()
    {
        return _lastRunningTask = _lastRunningTask.ContinueWith(p => ValidateEntitiesAsyncImpl()).Unwrap();
    }

    private Task ValidateEntitiesAsyncImpl()
    {
        return Task.Run(() =>
        {
            ChangeTracker.DetectChanges();
            List<DbEntityEntry> AllEntites = new List<DbEntityEntry>(ChangeTracker.Entries());

            try
            {
                foreach (DbEntityEntry entity in AllEntites)
                {
                    if (entity.State == EntityState.Deleted)
                        ((EntityBase)entity.Entity).readyToDelete();
                }
            }
            catch (ErrorException e)
            {
                fireError(e);
                throw e;
            }
            catch (Exception e)
            {
                return;
            }
            return;
        });
    }

    public Task RevertChangesAsync<TEntity>(CancellationToken token) 
        where TEntity : EntityBase
    {
        return _lastRunningTask = _lastRunningTask.ContinueWith(p => RevertChangesAsync<TEntity>(token)).Unwrap();
    }

    private Task RevertChangesAsyncImpl<TEntity>(CancellationToken token) where TEntity : EntityBase
    {
        return Task.Run(() => revertDummy<TEntity>(token));
    }
    private async void revertDummy<TEntity>(CancellationToken token) where TEntity : EntityBase
    {
        ChangeTracker.DetectChanges();
        List<DbEntityEntry<TEntity>> revertEntries = new List<DbEntityEntry<TEntity>>(ChangeTracker.Entries<TEntity>());

        foreach (DbEntityEntry entity in revertEntries)
        {
            await entity.ReloadAsync(token);
        }
    }
1
2
7/30/2015 9:35:55 AM

Popular Answer

ZZZ_tmp
3
7/30/2015 9:56:14 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow