Entity Framework and MongoClient with Task - c#

In a console application I'm starting from a list and open multiple tasks to handle them like:
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() => { Elabor(el.Take(1000).ToList(), listLogDequeues); }));
tasks.Add(Task.Run(() => { Elabor(el.Skip(1000).Take(1000).ToList(), listLogDequeues); }));
tasks.Add(Task.Run(() => { Elabor(el.Skip(2000).Take(1000).ToList(), listLogDequeues); }));
Task.WaitAll(tasks.ToArray());
el and ListLogDequeue is a ConcurrentBag<T> and inside the function an integer is incremented safely using Interlocked.Add.
This allow me to run three/four tasks and perform operations, but inside Elabor is used Entity Framework and MongoClient, as two repos injected with Ninject in my console application Main. Each function build and use it's context, but I don't get if and how concurrency and thread safety can hurt here.
EF:
public OutAnag GetAnagById(string id)
{
try
{
using (var c = new Context())
{
return c.Anag.AsNoTracking().FirstOrDefault(e => e.Id == id);
}
}
catch (Exception ex)
{
return null;
}
}
Mongo:
public bool SetElab(string guid)
{
Context dbContext = new Context();
try
{
var filter = Builders<Anag>.Filter.Where(m => m.Guid == guid);
var update = Builders<Anag>.Update.Set(m => m.DataElaborazione, DateTime.Now);
var options = new FindOneAndUpdateOptions<Anag>();
dbContext.Anag.FindOneAndUpdate(filter, update, options);
}
catch (Exception e)
{
return false;
}
return true;
}

Related

Task async with neo4jclient is not adding relationships in loop for all nodes

I am calling 2 async methods in loop.
First one is to create node and second is to add relation.
its creating node all time but its not creating all relationships
Eg - if there are 4 degrees , its creating 3 degrees but its not creating relationship with all 4. even if JobPost and JobDegrees both nodes are present.
Why its not creating relationship?
DegreesList - here I am passing array of an object.
Here is the code -
private void Map_Job_DEGREES(GUID JobId, dynamic DegreesList)
{
try
{
foreach (var objdegree in DegreesList)
{
string degreename = Convert.ToString(objdegree.name);
degreename = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(degreename);
JobDegrees objnew1 = new JobDegrees();
objnew1.name = degreename;
Task.Run(async () => await repo.Insert_JobDegrees(objnew1));
Task.Run(async () => await repo.CreateRelationship_DEGREES_INCLUDED(JobId, degreename));
}
}
catch { }
}
public class JobPostingNeo4jRepository
{
public async Task Insert_JobDegrees(JobDegrees obj1)
{
try
{
await _graphClient.ConnectAsync();
await _graphClient.Cypher
.Merge("(obj1:JobDegrees { name: $name })")
.OnCreate()
.Set("obj1 = $obj1")
.WithParams(new
{
name = obj1.name,
obj1
})
.ExecuteWithoutResultsAsync();
}
catch (Exception ex)
{
throw ex;
}
}
public async Task CreateRelationship_DEGREES_INCLUDED(Guid JobId, string name)
{
try
{
await _graphClient.ConnectAsync();
await _graphClient.Cypher
.Match("(obj1:JobPost)", "(obj2:JobDegrees)")
.Where((JobPost obj1) => obj1.Id == JobId)
.AndWhere((JobDegrees obj2) => obj2.name == name)
.Merge("(obj1)-[:DEGREES_INCLUDED { createddate: $createddate }]->(obj2)")
.WithParams(new { createddate = DateTime.UtcNow })
.ExecuteWithoutResultsAsync();
}
catch (Exception ex)
{
throw ex;
}
}
}

How to test 'ToListAsync' with a IsFaulted, IsCanceled and IsCompleted test cases

Hi guys I have a method like this:
public virtual async Task StartSearch()
{
CancellationTokenSource = new CancellationTokenSource();
Context = ContextFactory.Create();
SearchResults = await Task.Factory.StartNew(() =>
{
try
{
IsLoading = true;
var resultTask = GetResults().ToListAsync(CancellationTokenSource.Token);
while (!resultTask.IsCompleted && !resultTask.IsFaulted &&
!CancellationTokenSource.Token.IsCancellationRequested)
Thread.Sleep(100);
IsLoading = false;
if (resultTask.IsFaulted)
throw resultTask.Exception ??
new Exception("Some error.");
return resultTask.IsCompleted && !resultTask.IsCanceled ? resultTask.Result : null;
}
catch (Exception)
{
IsLoading = false;
throw;
}
}, CancellationTokenSource.Token) ?? SearchResults;
}
I wonder how could I mock up a Task (with all those IsFaulted, IsCompleted, IsCaneled fields) which I get from .ToListAsync() method?
I've found that they are not virtual so I cannot create a Task object to simply mock them.
Additional question is if it gives me something if I create my own dummy class and mock it for a test.
What are your suggestions? Maybe you don't want to mock it?
For now I only tested this to check if my method will return some data.
EDIT:
public abstract IQueryable<dynamic> GetResults();
and some exemplary implementation:
public override IQueryable<dynamic> GetResults()
{
var query = Context.Table.AsQueryable();
query = string.IsNullOrWhiteSpace(Field)
? query
: query.Where(table => table.Field.Contains(SomeFilter));
return query.Select(
table => new
{
table.Field1,
table.Field2,
table.Field3
}).OrderBy(table => table.Id);
}

How to create reportviewer with an asynchronous Task

My function has three parts.
Part one Parameter Popup
Part two Executes the code in a new thread with ApartmentState.STA turned on.
Part three - Show ReportViewer
I am currently receiving this error the calling thread cannot access this object because a different thread owns it.
public async void AnticipatedEntriesReport(bool fund)
{
var anticipatedReport = new AnticipatedReport(fund);
ReportPreviewForm report = new ReportPreviewForm();
anticipatedReport.InitializeParameters();
if (anticipatedReport.GetParameters() != null)
{
await RunAsyncTask(
() =>
{
report = anticipatedReport.GenerateReport(SelectedLoans);
});
report.Show();
}
}
My code breaks at report.Show().
anticipatedReport.GenerateReport returns a ReportPreviewForm.
I'm wondering what am I doing wrong? I think it's based on where I created the object.
public async Task RunAsyncTask(System.Action action)
{
try
{
await ThreadManager.StartSTATask(action);
}
catch (Exception ex)
{
}
}
public static Task StartSTATask(System.Action func)
{
var tcs = new TaskCompletionSource<object>();
var thread = new Thread(() =>
{
try
{
func();
tcs.SetResult(null);
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
Just create the report inside the task and return it to task's parent:
public async Task AnticipatedEntriesReport(bool fund)
{
var anticipatedReport = new AnticipatedReport(fund);
ReportPreviewForm report = null;
anticipatedReport.InitializeParameters();
if (anticipatedReport.GetParameters() != null)
{
// Generate the report inside the task and return it.
report = await RunAsyncTask(
() =>
{
var result = anticipatedReport.GenerateReport(SelectedLoans);
return result;
});
}
}
and in RunAsyncTask:
public async Task<TResult> RunAsyncTask<TResult>(Func<TResult> function)
{
TResult result = default(TResult);
UpdateBusyUi(true);
try
{
result = await ThreadManager.StartSTATask(function);
}
catch (Exception ex)
{
SendException(ex);
LoadSucceed = false;
Events.PublishOnUIThread(new BackgroundCompletedEvent { Header = BackgroundCompletedEvent.EntityActions.Error, Error = true });
}
UpdateBusyUi(false);
return result;
}
The StartSTATask:
Task<TResult> StartSTATask<TResult>(Func<TResult> function)
{
TaskCompletionSource<TResult> source = new TaskCompletionSource<TResult>();
Thread thread = new Thread(() =>
{
try
{
source.SetResult(function());
}
catch (Exception ex)
{
source.SetException(ex);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return source.Task;
}

Unit test is running forever with Tasks

I have a unit test which is running forever:
[Test]
public bool test()
{
manager.Send(10);
Thread.Sleep(1000);
manager.Messages.Should().HaveCount(10);
return true;
}
manager.Send() method is:
private void Send()
{
try
{
var entities = GetAllEntities();
foreach (var group in entities.GroupBy(r => r.Priority))
{
var tasks = group.Select(entity => Task.Factory.StartNew(() => manager.SendEntity(entity))).ToList();
Task.WaitAll(tasks.ToArray());
if (tasks.All(r => r.Result.Result == true))
{
// some code here...
}
}
}
catch (Exception e)
{
logger.FatalException(e.Message, e);
}
finally
{
logger.Info("End...");
}
}
and SendEntity() method:
public Task<bool> SendEntity(DeferredEntity entity)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
try
{
logger.Info("Sending entity {0} with params: {1}", entity.Entity, GetEntityParams(entity));
server.SendToServer(entity, (response, result) =>
{
taskCompletionSource.SetResult(result);
});
}
catch (Exception e)
{
logger.FatalException(e.Message, e);
}
return taskCompletionSource.Task;
}
in unit test manager.Send(10) is running forever. I debuged the code and I see that the problem is in
if (tasks.All(r => r.Result.Result == true))
the debugger stops on this line and sleeps forever. What I am doing wrong? I added return value of unit test method to bool (async methods doesn't throw exceptions in void methods). But it doesn't help. Do you have any suggestions?
You get the deadlock there.
First of all you don't have to start the new Thread with
Task.Factory.StartNew(() => manager.SendEntity(entity)
It seems SendToServer is already async.
It also a bad practice to use the Task.Wait***/Task.Result, use the async flow
private async Task Send()
{
try
{
var entities = GetAllEntities();
foreach (var group in entities.GroupBy(r => r.Priority))
{
var tasks = group
.Select(entity => manager.SendEntity(entity))
.ToArray();
var results = await Task.WhenAll(tasks);
if (results.All(result => result))
{
// some code here...
}
}
}
catch (Exception e)
{
logger.FatalException(e.Message, e);
}
finally
{
logger.Info("End...");
}
}
But if you don't want to rewrite the Send Method you can use .ConfigureAwait(false)
return taskCompletionSource.Task.ConfigureAwait(false);
But anyway, remove the StartNew - you don't need this.

can a method with return type as list be called from a thread

I have a method, shown below, which calls a service.
How can I run this method through thread?
public List<AccessDetails> GetAccessListOfMirror(string mirrorId,string server)
{
List<AccessDetails> accessOfMirror = new List<AccessDetails>();
string loginUserId = SessionManager.Session.Current.LoggedInUserName;
string userPassword = SessionManager.Session.Current.Password;
using (Service1Client client = new Service1Client())
{
client.Open();
accessOfMirror = client.GetMirrorList1(mirrorId, server, null);
}
return accessOfMirror;
}
In C# 3.5 or 4.0 you can do this.
var task = Task.Factory.StartNew<List<AccessDetails>>(() => GetAccessListOfMirror(mirrorId,server))
.ContinueWith(tsk => ProcessResult(tsk));
private void ProcessResult(Task task)
{
var result = task.Result;
}
In C# 4.5 there's the await/async keywords which is some sugar for above
public async Task<List<AccessDetails>> GetAccessListOfMirror(string mirrorId,string server)
var myResult = await GetAccessListOfMirror(mirrorId, server)
Try something like this:
public async Task<List<AccessDetails>> GetAccessListOfMirror(string mirrorId, string server)
{
List<AccessDetails> accessOfMirror = new List<AccessDetails>();
string loginUserId = SessionManager.Session.Current.LoggedInUserName;
string userPassword = SessionManager.Session.Current.Password;
using (Service1Client client = new Service1Client())
{
client.Open();
Task<List<AccessDetails>> Detail = client.GetMirrorList1(mirrorId, server, null);
accessOfMirror = await Detail;
}
return accessOfMirror;
}
Below is a helper class I use, it references RX.NET.
If you include that in your project, then you can thread stuff very simply - the code above you could spin off to a separate thread as follows:
int mirrorId = 0;
string server = "xxx";
ASync.Run<List<AccessDetails>>(GetAccessListOfMirror(mirrorId,server), resultList => {
foreach(var accessDetail in resultList)
{
// do stuff with result
}
}, error => { // if error occured on other thread, handle exception here });
Worth noting: that lambda expression is merged back to the original calling thread - which is very handy if you're initiating your async operations from a GUI thread for example.
It also has another very handy method: Fork lets you spin off multiple worker threads and causes the calling thread to block until all the sub-threads are either complete or errored.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Concurrency;
namespace MyProject
{
public static class ASync
{
public static void ThrowAway(Action todo)
{
ThrowAway(todo, null);
}
public static void ThrowAway(Action todo, Action<Exception> onException)
{
if (todo == null)
return;
Run<bool>(() =>
{
todo();
return true;
}, null, onException);
}
public static bool Fork(Action<Exception> onError, params Action[] toDo)
{
bool errors = false;
var fork = Observable.ForkJoin(toDo.Select(t => Observable.Start(t).Materialize()));
foreach (var x in fork.First())
if (x.Kind == NotificationKind.OnError)
{
if(onError != null)
onError(x.Exception);
errors = true;
}
return !errors;
}
public static bool Fork<T>(Action<Exception> onError, IEnumerable<T> args, Action<T> perArg)
{
bool errors = false;
var fork = Observable.ForkJoin(args.Select(arg => Observable.Start(() => { perArg(arg); }).Materialize()));
foreach (var x in fork.First())
if (x.Kind == NotificationKind.OnError)
{
if (onError != null)
onError(x.Exception);
errors = true;
}
return !errors;
}
public static void Run<TResult>(Func<TResult> todo, Action<TResult> continuation, Action<Exception> onException)
{
bool errored = false;
IDisposable subscription = null;
var toCall = Observable.ToAsync<TResult>(todo);
var observable =
Observable.CreateWithDisposable<TResult>(o => toCall().Subscribe(o)).ObserveOn(Scheduler.Dispatcher).Catch(
(Exception err) =>
{
errored = true;
if (onException != null)
onException(err);
return Observable.Never<TResult>();
}).Finally(
() =>
{
if (subscription != null)
subscription.Dispose();
});
subscription = observable.Subscribe((TResult result) =>
{
if (!errored && continuation != null)
{
try
{
continuation(result);
}
catch (Exception e)
{
if (onException != null)
onException(e);
}
}
});
}
}
}

Categories

Resources