The following code enters GetIds method and never return.
public static class ANameOrchestrator
{
[FunctionName(CommonNames.AName)]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var entityId = new EntityId(nameof(Documents), CommonNames.DocFlowFifo);
var px = context.CreateEntityProxy<IDocuments>(entityId);
IEnumerable<int> list = await px.GetIds();//never return or throw
}
}
I tried to wrap the method call with LockAsync in which case the execution deadlocked on the call.
public static class ANameInOrchestrator
{
[FunctionName(CommonNames.AName)]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
IEnumerable<int> list;
var entityId = new EntityId(nameof(Documents), CommonNames.DocFlowFifo);
using (var lk = await context.LockAsync(entityId)) //never goes beyond the call to LockAync
{
var x = context.CreateEntityProxy<IDocuments>(entityId);
list = await x.GetIds();
}
}
}
How to resolve the problem? What direction do I have to look?
Edit
using alternative version to call the entity operation doesn't work either
list = await context.CallEntityAsync<IEnumerable<int>>(entityId, nameof(Documents.GetIds));
Related
I have the following SignalR Hub with in-memory connection management.
[Authorize]
public class ChatHub : Hub
{
private static readonly ConnectionMapping<string> _connections =
new ConnectionMapping<string>();
private readonly IMessageRepository _messagesRepository;
public ChatHub(IMessageRepository messageRepository)
{
_messagesRepository = messagesRepository;
}
public override async Task OnConnectedAsync()
{
var name = Context.User.Identity.Name;
_connections.Add(name, Context.ConnectionId);
//await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
var name = Context.User.Identity.Name;
_connections.Remove(name, Context.ConnectionId);
//await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnDisconnectedAsync(exception);
}
public async void SendMessage(ChatMessage chatMessage)
{
var name = Context.User.Identity.Name;
var chatHistoryMessage = await _messagesRepository.SaveMessageAsync(chatMessage);
var availableConnections = _connections.GetConnections(name);
if (availableConnections.Any())
{
foreach (var connectionId in availableConnections)
{
Clients.Client(connectionId).SendAsync("ReceiveMessage", chatHistoryMessage);
}
}
else
{
}
}
}
However, when executing the code the following line
Clients.Client(connectionId).SendAsync("ReceiveMessage", 1);
raises an object disposed error on Clients.
This issue started happening when I added the repository line:
var chatHistoryMessage = await _messagesRepository.SaveMessageAsync(chatMessage);
SaveMessageAsync method:
public async Task<ChatHistory> SaveMessageAsync (ChatMessage chatMessage)
{
using (var conn = new SqlConnection(ConnProvider.ConnectionString))
{
await conn.OpenAsync();
return (await conn.QueryAsync<ChatHistory>("[mob].[spSaveChatMessage]",
new
{
..
},
commandType: CommandType.StoredProcedure)).FirstOrDefault();
}
}
Why would my Clients object be disposed? If I wait with the debugger that issue never happens.
It looks like the SendMessage method should be an async Task rather than an async void.
The issue could be caused by the way the SignalR framework runs async voids.
See this article for a good overview.
Async methods returning void don’t provide an easy way to notify the
calling code that they’ve completed.
I am trying to use an async task to read from my sqlite db using sqlite.net and my basic class is this one below:
public class Students
{
public string Fullname { get; }
public string Admnumber { get; }
}
A quick example of implementing this library is:
public static IEnumerable<Students> QueryVals ()
{
var db = new SQLiteConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.Query<Students> ("select * from students");
}
but now when I try to use it an async task as below:
public static Task<Students> GetStudentsList ()
{
var db = new SQLiteConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.Query<Students> ("select * from students");
}
I get an error:
Cannot implicitly convert type
'System.Collection.Generic.List' to
'System.Threading.Tasks.Task'
even tyring this doesn't work:
private async void Init()
{
IsBusy = true;
var db = new SQLiteConnection("Data Source=assets\\mydb.db;New=False;Version=3");
var myitems = await db.Query<Students>("select * from students");
IsBusy = false;
}
before I finish it gives the error that my class Students does not have GetAwaiter
You can't just make something asynchronous by changing the return type to Task<T>. Firstly, you need to switch to using the SQLiteAsyncConnection object and the async version of the Query method:
new SQLiteAsyncConnection("...");
...
db.QueryAsync<Students>("select * from students");
// ^^^^^
// Add this
Now you have two options. The first is to await the result, as shown in the answer by mm8. The other, and probably the one I would choose is to just return the task and let the caller await:
public static Task<IEnumerable<Students>> GetStudentsListAsync()
{
var db = new SQLiteAsyncConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.QueryAsync<Students>("select * from students");
}
Note I'm also using the common convention of renaming the method to indicate it is async.
A method that returns a Task<T> is supposed to either be async and await something or return a Task.
You could add the async keyword to your method and await the asynchronous QueryAsync method:
public static async Task<IEnumerable<Students>> GetStudentsListAsync()
{
var db = new SQLiteAsyncConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return await db.QueryAsync<Students>("select * from students");
}
Or return an uncompleted task to be awaited by the caller of the method:
public static Task<IEnumerable<Students>> GetStudentsListAsync()
{
var db = new SQLiteAsyncConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.QueryAsync<Students>("select * from students");
}
I'am trying to run my Controller Action in async way.
How do I use async Task ? Or How to run in async way
// Db context
public class DeptContext : DbContext
{
public LagerContext(DbContextOptions<LagerContext> options)
: base(options)
{
Database.Migrate();
}
public DbSet<Department> Departments { get; set; }
public DbSet<Product> Products { get; set; }
}
// This is my Interface IDepRepository
Task<Department> GetDepartmentWithOrWithoutProducts(int deptId, bool includeProducts);
// And my Repository class DepRepository
public class DepRepository : IDepRepository
{
private DeptContext db;
public DepRepository(DeptContext context)
{
db = context;
}
// I'am geting Department name with products or Without products
public async Task<Department> GetDepartmentWithOrWithoutProducts(int deptId, bool includeProducts)
{
if(includeProductss)
{
return await db.Departments.Include(c => c.Products).Where(s => s.deptId == deptId).SingleAsync();
}
return await db.Departments.Where(s => s.deptId == deptId).SingleAsync();
}
}
So How should I do now in my Controller to do it as async way: I tried as following but I don't know if it's right to do like this following:
I'm not getting any error but I don't if it's right way ...
using System.Threading.Tasks;
using System.Net;
using Microsoft.Data.Entity;
using Microsoft.EntityFrameworkCore;
[Route("api/departments")]
public class DepartmentsController : Controller
{
private IDeptRepository _deptInfoRepository;
public DepartmentsController(IDeptRepository deptInfoRepository)
{
_deptInfoRepository = deptInfoRepository;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetDepatment(int id, bool includeProducts = false)
{
var dept = _deptInfoRepository.GetDepartmentWithOrWithoutProducts(id, includeComputers);
if(dept == null)
{
return BadRequest();
}
if(includeProducts)
{
var depResult = new DepartmentDto() { deptId = dept.deptId, deptName = dept.deptName };
foreach(var department in dept.Products)
{
depResult.Products.Add(new ProductDto() { productId = department.productId, deptId = department.deptId, ProductName = department.ProductName });
}
return Ok(depResult);
}
var departmentWithoutProductResult = new DepartmentsWithoutProductsDto() { DeptId = dept.deptId, DeptName = dept.DeptName};
return Ok(departmentWithoutProductResult);
}
How do I do to get my controller in async way.. I don't know where to put those await and ToListAsync(). Thank you in advance!
The interface should be renamed to better show the intent.
public interface IDepRepository {
Task<Department> GetDepartmentWithOrWithoutProductsAsync(int deptId, bool includeProducts);
//...
}
Which would update the implementation accordingly. Since the method is not actually using anything after the async call then there not really any reason to tag the method as async. Just return the Task.
public Task<Department> GetDepartmentWithOrWithoutProductsAsync(int deptId, bool includeProducts) {
if(includeProductss) {
return db.Departments.Include(c => c.Products).Where(s => s.deptId == deptId).SingleAsync();
}
return db.Departments.Where(s => s.deptId == deptId).SingleAsync();
}
The controller action however needs to await the task and then continue after the task has completed so therefore that method will be tagged with async.
[HttpGet("{id}")]
public async Task<IActionResult> GetDepatment(int id, bool includeProducts = false) {
var dept = await _deptInfoRepository.GetDepartmentWithOrWithoutProductsAsync(id, includeComputers);
if (dept == null) {
return BadRequest();
}
if (includeProducts) {
var depResult = new DepartmentDto() { deptId = dept.deptId, deptName = dept.deptName };
foreach (var department in dept.Products) {
depResult.Products.Add(new ProductDto() {
productId = department.productId,
deptId = department.deptId,
ProductName = department.ProductName
});
}
return Ok(depResult);
}
var departmentWithoutProductResult = new DepartmentsWithoutProductsDto() { DeptId = dept.deptId, DeptName = dept.DeptName};
return Ok(departmentWithoutProductResult);
}
What I can't tell from your code is the datatype of what GetDepartments returns. My guess is that you are using EF Core and GetDepartments returns a DbSet or a LINQ query against a DbSet. If that is the case, then after the line where your depEntities variable is set, that variable points to a deferred object (an expression tree that has not been evaulated yet). Or in other words, the actual query has not been sent to the database yet. When you loop over the depEntities (with your foreach loop), you are causing the actual potentially long-running work to occur (database access). That's what you want to await on. So, yes, you could make an async version of GetDepartments or you could also probably change your code to be:
var depEntities = await _depRepository.GetDepartments().ToListAsync();
The call to ToListAsync will enumerate the deferred object and perform the database access. Your return statement would just return results. Behind the scenes, the method actually returns on your await statement and resumes after the work you're awaiting on completes.
One last note.. any database exceptions will occur at the point where the deferred object is enumerated.
You should not do any await on already-prepared results list. It's already contain required data - what you want to wait to?
You should make new async version of your GetDepartments() method and await while obtaining data from repository:
var depEntities = await _depRepository.GetDepartmentsAsync();
I am trying to implement a async await in my web application for calling a soap service. I have dependency injection implemented which works fine when i make calls to the database.
When i try calling the webservice i get the response but once it exists the query it's a deadlock. I am not able to figure out what's going wrong. I am new to this async stuff appreciate your inputs on this.
This is the way i am calling the services in a mvc application to invoke the call
public void GetPersonData()
{
var persons = queryProcessor.Process(new GetPersonsWhichNeedApiCalls());
var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
SearchAPI(persons).Wait();
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
}
private async Task SearchAPI(IEnumerable<Person> persons)
{
var tasks = persons.Select(async eachPerson =>
{
var result = await asyncQueryProcessor.ProcessAsync(new PersonSearchCall { Name = eachPerson.Name, Id = eachPerson.Id });
commandProcessor.Process(new CreatePersonSearch()
{
PersonSearch = result
});
});
await Task.WhenAll(tasks);
}
query:
namespace Sample.AsyncQueries
{
public class PersonSearchCall : IQuery<PersonSearch>
{
public string Name { get; set; }
public int Id { get; set; }
}
public class PersonSearchCallHandler : IAsyncQueryHandler<PersonSearchCall, PersonSearch>
{
private readonly IQueryProcessor queryProcessor;
private readonly ICommandProcessor commandProcessor;
public PersonSearchCallHandler(ICommandProcessor commandProcessor,
IQueryProcessor queryProcessor)
{
this.queryProcessor = queryProcessor;
this.commandProcessor = commandProcessor;
}
public async Task<PersonSearch> HandleAsync(PersonSearchCall query)
{
var client = new PersonServiceSoapClient();
var personResponses = await client.PersonSearchAsync(inputs).ConfigureAwait(false);
//Build the person Object
return person;
}
}
}
This simple injector i was able to achieve this using the synchronous way but as i am calling a list of persons and each call is taking around 2sec. i am trying to leverage the use of async and await to make multiple calls from the list.
As StriplingWarrior commented, your problem is that you're blocking on async code. You need to use async all the way:
public async Task GetPersonData()
{
var persons= queryProcessor.Process(new GetPersonsWhichNeedApiCalls());
var watch = System.Diagnostics.Stopwatch.StartNew();
await SearchAPI(persons);
var elapsedMs = watch.ElapsedMilliseconds;
}
I have a simple Web API method that looks like this:
public async Task<HttpResponseMessage> RunTask(TaskType taskType)
{
var taskId = await TaskManager.CreateTask(taskType);
TaskManager.Run(taskId);
return new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content =
new StringContent($"Task {taskType.GetDescription()} was started.")
};
}
TaskManager.Run is decalared like this:
public async Task Run(int id)
I was expecting it to return "Task was started" message immediately after TaskManager.Run(taskId) But the request continues to run synchronously.
But if to replace the call TaskManager.Run(taskId) with:
Task.Run(() => Thread.Sleep(TimeSpan.FromSeconds(100)));
Then it runs asynchronously.
So I believe this is something to do with the resources shared by TaskManager and main thread. Can a shared resource lock the execution?
I'm using Castle Windsor. One WindsorContainer container is declared in Web API project.
TaskManager utilizes BaseTaskRunner class inside of it. One more WindsorContainer is declared in BaseTaskRunner.
Web API's container uses LifeStyle.PerWebRequest for all components. BaseTaskRunner's container uses LifeStyle.Singleton (not sure if it's correct LifeStyle). Could the call be locked for example by DdContext or other classes declared in both of the containers?
UPD:
I don't want to wait the TaskManager.Run to complete. But what happens is that return statement still waits for the TaskManager.Run to complete (even without await statement on TaskManager.Run).
In other words it does not matter how I call the TaskManager.Run:
TaskManager.Run(taskId);
or
await TaskManager.Run(taskId);
It waits for TaskManager.Run to complete in both cases.
Here is the code of TaskManager:
public class TaskManager : ITaskManager
{
public IRepository<BackgroundTask> TaskRepository { get; set; }
public async Task<int> CreateTask(TaskType type, byte[] data = null, object config = null)
{
var task = new BackgroundTask
{
Type = type,
Status = BackgroundTaskStatus.New,
Config = config?.SerializeToXml(),
Created = DateTime.Now,
Data = data
};
TaskRepository.Add(task);
TaskRepository.SaveChanges();
return task.Id;
}
public async Task Run(int id, bool removeOnComplete = true)
{
var task = TaskRepository.GetById(id);
Run(task, removeOnComplete);
}
public async Task Run(TaskType type, bool removeOnComplete = true)
{
var tasksToRun = TaskRepository.Get(t => t.Type == type);
tasksToRun.ForEachAsync(t => Run(t, removeOnComplete));
}
public async Task Run(BackgroundTask task, bool removeOnComplete = true)
{
switch (task.Type)
{
case TaskType.SpreadsheetImport:
new SpreadsheetImportTaskRunner().Run(task);
break;
}
}
}
And some other classes:
public class SpreadsheetImportTaskRunner : BaseTaskRunner
{
public IForecastSpreadsheetManager SpreadsheetManager { get; set; }
protected override void Execute()
{
SpreadsheetManager.ImportActuals(Task.Data);
}
protected override void Initialize()
{
base.Initialize();
SpreadsheetManager = _container.Resolve<IForecastSpreadsheetManager>();
}
}
BaseTaskRunner:
public class BaseTaskRunner
{
public IRepository<BackgroundTask> TaskRepository { get; set; }
protected IWindsorContainer _container = new WindsorContainer();
protected BackgroundTask Task { get; set; }
public async Task Run(BackgroundTask task)
{
Initialize();
Task = task;
try
{
Execute();
}
catch (Exception ex)
{
SetError(ex.ToString());
}
}
protected virtual void Execute()
{
}
protected virtual void Initialize()
{
_container.Install(new TaskRunnerComponentsInstaller());
TaskRepository = _container.Resolve<IRepository<BackgroundTask>>();
}
}
I still believe this is something to do with the WindsorContainer and common classes which are resolved in several different threads.
The issue is that you're not using await on the Task being returned from the invocation of the TaskManager.Run function. Consider the below:
public async Task<HttpResponseMessage> RunTask(TaskType taskType)
{
var taskId = await TaskManager.CreateTask(taskType);
await TaskManager.Run(taskId);
return new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content =
new StringContent($"Task {taskType.GetDescription()} was started.")
};
}
Now it will work asynchronously as you'd expect. The await sets a continuation marker in the async state-machine, instructing it to return to this portion of the method upon completion of the asynchronous operation defined in the TaskManager.Run.
UPDATE
You are missing lots of await statements, and there are times where you need to not mark methods as async. It appears as though there are some mis-understandings as it pertains to these keywords. Here is what your TaskManager class should look like.
public class TaskManager : ITaskManager
{
public IRepository<BackgroundTask> TaskRepository { get; set; }
public async Task<int> CreateTask(TaskType type,
byte[] data = null,
object config = null)
{
var task = new BackgroundTask
{
Type = type,
Status = BackgroundTaskStatus.New,
Config = config?.SerializeToXml(),
Created = DateTime.Now,
Data = data
};
TaskRepository.Add(task);
TaskRepository.SaveChanges();
return task.Id;
}
public ask Run(int id, bool removeOnComplete = true)
{
var task = TaskRepository.GetById(id);
return Run(task, removeOnComplete);
}
public Task Run(TaskType type, bool removeOnComplete = true)
{
var tasksToRun = TaskRepository.Get(t => t.Type == type);
return tasksToRun.ForEachAsync(t => Run(t, removeOnComplete));
}
public Task Run(BackgroundTask task, bool removeOnComplete = true)
{
switch (task.Type)
{
case TaskType.SpreadsheetImport:
return new SpreadsheetImportTaskRunner().Run(task);
break;
}
}
}
}
Ideally, if the method is marked as a return type of Task and the method doesn't need to unwind any tasks within its execution it can simply return the Task functionality for its implementation. For example, notice how dramatically my TaskManager class differs from yours -- I'm only marking methods as async that need to actually await. These two keywords should be married, if a method uses async there should be an await. But only use await if the method needs to unwind and use the asynchronous operation.