What is default behavior InsertEvent or InsertEventAsync - audit.net

For data providers that allow asynchronous operations, is the standard asynchronous method used?
If not, how do I deify this behavior?

I'm not sure what you mean with deify the behavior, but most of the data providers implements both the sync and async methods, for example the FileDataProvider:
https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.NET/Providers/FileDataProvider.cs
However, the base class of the data providers calls the sync method from the virtual async methods, so if a custom data provider does not overrides the async methods, they will just call the sync method within a new task:
https://github.com/thepirat000/Audit.NET/blob/8d410cb919f09d0c35f7c622d2e21913bcc46c59/src/Audit.NET/AuditDataProvider.cs#L58
public virtual async Task<object> InsertEventAsync(AuditEvent auditEvent)
{
// Default implementation calls the sync operation
return await Task.Factory.StartNew(() => InsertEvent(auditEvent));
}
Which one is called depends on the context. If you call the Save() or SaveAsync() method on the AuditScope, it will call the sync or async version respectively. And the same happens for Dispose() / DisposeAsync() methods.
Consider the following example:
Audit.Core.Configuration.Setup()
.UseSqlServer(sql => sql....)
.WithCreationPolicy(EventCreationPolicy.InsertOnEnd);
using (var scope = AuditScope.Create("test", () => target, null))
{
target.Status = "Updated";
} // <---- Dispose() will call InsertEvent()
await using (var scope = await AuditScope.CreateAsync("test", () => target, null))
{
target.Status = "Updated";
} // <---- DisposeAsync() will call InsertEventAsync()

Related

Dart Lang: Avoid marking all functions with async

Dart newbie here, I'm currently learning about asynchronous execution in Dart. I'm a bit irritated about how concurrency works in Dart, take the following scenario from their codelab:
void printOrderMessage () async {
try {
var order = await fetchUserOrder();
print('Awaiting user order...');
print(order);
} catch (err) {
print('Caught error: $err');
}
}
Future<String> fetchUserOrder() {
// Imagine that this function is more complex.
var str = Future.delayed(Duration(seconds: 4), () => throw 'Cannot locate user order');
return str;
}
Future<void> main() async {
await printOrderMessage();
}
In this case, the asynchronous operation is fetching the the user order from say a DB. Now because of Dart's await / async mechanism, every function that is related to the async operation is required to have a Future<> return type and must be tagged with async.
This feels clunky ... Imagine if some value deep in my function chain is being calculated asynchronously, would I really need to always return a future? Is there some other construct to synchronize code in Dart than await? Or have I misunderstood the concept?
If callers need to be able to wait for your asynchronous operation to finish, then your asynchronous function must return a Future that can be awaited. This is contagious; if callers of those callers need to be able to wait, then they too need to have Futures to wait upon.
If callers should not wait, then you can have a "fire-and-forget" function that does not need to return a Future:
Future<void> foo() {
// ...
}
// Does not need to return a Future. Consequently, callers cannot
// directly determine when `foo` completes.
void bar() {
foo();
}

Returning from an async method in a SignalR Core hub

I have an ASP .Net Core 2.2 Web API. In it I am using SignalR. In my hub, I need to save messages to the database, so I am getting an instance of DbContext, and because I am calling the SaveChangesAsync() method of DbContext, I need to make the method async. So, from
public Task SendMessageToAll(string message)
{
return Clients.All.SendAsync("ReceiveMessage", message);
}
I now have
public async Task SendMessageToAll(string message)
{
using (var scope = _serviceProvider.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<DbContext>();
Message newMessage = new Message()
{
Body = message,
Timestamp = DateTime.Now
};
dbContext.Messages.Add(newMessage);
await dbContext.SaveChangesAsync();
}
return Clients.All.SendAsync("ReceiveMessage", message);
}
However, now I'm getting this error:
Since 'ChatHub.SendMessageToAll(string)' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'?
Which makes sense, but I'm not sure how to fix it. Any ideas?
Change your code as below:
return Clients.All.SendAsync("ReceiveMessage", message);
await Clients.All.SendAsync("ReceiveMessage", message);

Asynchronous call via asp.net mvc core controller using the IOC

I’m trying to understand how to speed up long running processes that don’t need to be synchronous. Think “multiple query results” to display in a dashboard. I’m using .Net Core with DI and the built in IOC.
I want to call the RequirementsService.Fire() method via the IRequirementsService interface from the Overview() method. Objective is to fire off each Fire() method so that the logic for each method call can run simultaneously with the others. I need to return results to the caller.
The below solution runs synchronous still… I think I have a syntax issue but VS is not bawking at anything, just warning me that it will run synchronously from the Overview() method.
//Controller
public async Task<ActionResult> Overview()
{
//_requirement service is injected at controller constructor which I removed for brevity.
var fireOne = await _requirement.Fire(10000, "Fire 1");
var fireTwo = await _requirement.Fire(5000, "Fire 2");
var fireThree = await _requirement.Fire(1000, "Fire 3");
return View(model);
}
//Interface
public interface IRequirementsService
{
Task<int> Fire(int number, string fireCount);
}
//Service
public class RequirementsService : IRequirementsService
{
...
public async Task<int> Fire(int number, string fireCount)
{
int TimeOne = 0;
Thread.Sleep(10000 + number);
TimeOne = (10000 + number)/1000;
Debug.WriteLine(fireCount + TimeOne);
return TimeOne;
}
}
If you want to execute your Fire method three times and not have each call successively block the next one, you could do:
Task.WaitAll(_requirement.Fire(10000, "Fire 1"),
_requirement.Fire(5000, "Fire 2"),
_requirement.Fire(1000, "Fire 3"))
Also, use Task.Delay instead of Thread.Sleep to avoid blocking the thread.
Making the Controller method to have async nature is not advisible and not a good practise too.How ever you can call async method and combine them in your controller using WhenAll method as below
public async Task<ActionResult> Overview()
{
//_requirement service is injected at controller constructor which I removed for brevity.
var fireOne = await _requirement.Fire(10000, "Fire 1");
var fireTwo = await _requirement.Fire(5000, "Fire 2");
var fireThree = await _requirement.Fire(1000, "Fire 3");
ActionResult[] result = await Task.WhenAll(fireOne , fireTwo,fireThree);
return View(model);
}
I would suggest you with this link for more information on this.

Web API Post not returning response

I have a Web API that gets call by this method:
public async Task<Model> AddModel(string token, Model newModel)
{
HttpContent content = await HttpHelper.Request(token, baseUrl, url, newModel, HttpRequestType.POST);
return await content.ReadAsAsync<Model>();
}
The Web API is successfully called and I can add a Model. This is the Web API method that gets called:
[Route("webapi/models/addModel")]
[HttpPost]
public async Task<ModelDto> AddWithoutResetingDefault(ModelDto newModel)
{
ModelService modelService = new ModelService();
return modelService.AddModel(newModel);
}
The problem is after the successful add, it doesn't return to the calling code anymore (I have a breakpoint that doesn't get hit). There are no console errors in the browser, I enclosed in a try-catch the calling code and the called code but there were no exceptions thrown.
Also, after the first click to add, if I try to refresh the browser, it takes a really long time to reload the browser (I don't know if being async has something to do with it).
(I don't know if being async has something to do with it) - Yes it has
your Api method
public async Task<ModelDto> AddWithoutResetingDefault(ModelDto newModel)
{
ModelService modelService = new ModelService();
return modelService.AddModel(newModel);
}
is marked as Async method, but the code inside is Sync. And that is the problem, if your modelService.AddModel(newModel); is async, then do
return await modelService.AddModel(newModel);
if its not then there is no point in making the AddWithoutResetingDefault
method async, hence remove Aysnc and simply do a sync method like
public ModelDto AddWithoutResetingDefault(ModelDto newModel)
{
ModelService modelService = new ModelService();
return modelService.AddModel(newModel);
}

How I can safely run async code, when handling messages from Messenger?

I am using MVVM, inparticular MVVMLight. For boradcasting to all of my modelviews, that no internet connection is available I am using Messenger class. The modelviews subscribe to this event in order to reload itself with offline data, inform user etc.
However, I have a problem. When I have the folowing handler:
private void HandleNoInternetMessage(NoInternetAccessMessage obj)
{
Task.Run(async () => await InitializeForOfflineInternalAsync());
}
public async Task InitializeForOfflineInternalAsync()
{
try
{
WaitingLayerViewModel.ShouldBeVisible = true;
WaitingLayerViewModel.IsBusy = true; //<--exception HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)
bool switchToOffline = await CommonViewModelProvider.InformUserOfNoInternetAccessAndChangeAppState(); //<!- CoreWindow.GetForCurrentThread().Dispatcher is null
await FilterTestItemViewModel.InitializeForOfflineAsync();
await FilterTestItemViewModel.InitializeForOfflineAsync();
WaitingLayerViewModel.ShouldBeVisible = false;
WaitingLayerViewModel.IsBusy = false;
...
}
}
I got exception HRESULT: 0x8001010E (RPC_E_WRONG_THREAD), because in InitializeForOfflineInternalAsync I am changing some properties of the viewmodel wchich are bound in XAML (or at least I think it is because of that). However, it is weird, because I am changing in other code bound properties regularly and have no problems with it (and the thread is a working thread).
Now, how can i solve that?
The messanger let me provide only delegate which is not async (which make kind of sense), so I can not have the HandleNoInternetMessage method async
I am using async await ... no explicit spawning of threads
I dont have access in VM to Dispatcher, because I am in VM which should not know about platform dependent stuff. And when I tried to use it to show a message, NullPointer excpetion was thrown when calling CoreWindow.GetForCurrentThread().Dispatcher; And again when calling from other places, no such exception was thrown
I guess the question is How I can safely run async code, which changes boudn properties, when handling messages from Messenger?
You're responding to messages that are logically events, so this is an acceptable use case for async void.
private async void HandleNoInternetMessage(NoInternetAccessMessage obj)
{
await InitializeForOfflineInternalAsync();
}
public async Task InitializeForOfflineInternalAsync()
{
try
{
WaitingLayerViewModel.ShouldBeVisible = true;
WaitingLayerViewModel.IsBusy = true;
bool switchToOffline = await CommonViewModelProvider.InformUserOfNoInternetAccessAndChangeAppState();
await FilterTestItemViewModel.InitializeForOfflineAsync();
await FilterTestItemViewModel.InitializeForOfflineAsync();
WaitingLayerViewModel.ShouldBeVisible = false;
WaitingLayerViewModel.IsBusy = false;
...
}
}
Remember that Task.Run is for CPU-bound code (as I describe on my blog).

Resources