1

I did not find similar questions/answers for my purpose.

In few Actions of my Controllers (MVC 4/ EF 5 application) I have functions for updating of database, but these functions are not affect on user output (functions of updating information after selecting). And I want to send these functions in asynchronous threads (which will finished after user get a rendered page). I do not want to wait finishing of threads and render page. What about database context in this case? My context lifetime is "per request" and it deletes in Application_EndRequest:

protected virtual void Application_EndRequest()
{
    var entityContext = HttpContext.Current.Items["_Context"] as DbContext;
    if (entityContext != null)
        entityContext.Dispose();
}

I use own contexts in threads (using blocks for correct disposing).

using (DbContext db = new DbContext())
{
    ....
}

But if I want to Attach entity to DbContext in thread I get an error "An object with the same key already exists in the ObjectStateManager" in several cases. It is weird, because I use loading with AsNoTracking() option and entity state is "detached" in main Context before call new thread. In other case, when I am trying the request entity from database once again in thread and modify it (instead of attaching) I have an error "The object is in a detached state" several times Are the two instance of Context using one ObjectStateManager? And errors appear in dependence on time of main thread Context disposing. I mean before or after disposing main Context I use context in thread...

How can I work with asynchronous threads with own Context in this situation? Thanks.

2 Answers 2

2

You have a couple of problems here:

1) If you take an object, or it's navigation properties, that belong to one context and try to use them in another context, you will get the errors you have seen.

2) As soon as your request completes, IIS is free to recycle the AppDomain. When this happens in production, your worker threads will be aborted with extreme predjudice. That means you cannot rely on the worker threads doing anything at all.

If you want to defer some expensive work, you should pass the work to some sort of message queue implemented in another process - most probably a Windows Service.

Sign up to request clarification or add additional context in comments.

1 Comment

I do not know about 1). I wrote eager loading with AsNoTracking(). Entity is detached from context... Also navigation properties. About 2) - may be... Thanks.
0

I found the answer and all works. Start a long time background task. You can pass the Task StartNew() method a parameter that indicates the task you're starting is "long running", which provides a hint to the Task Scheduler to start the task on a new thread.

var task = Task.Factory.StartNew(Stuff, TaskCreationOptions.LongRunning);

Thanks, medkg15

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.