Currently i have a web application and a wins form application in my server. Basically, the web application will receive request from user and this request will be send to the wins form application to proceed (wins form need about 1 minute to complete a request).
Let say 2 users send a request at the same time via web application, I need to develop a queue job to maintain the request in sequence.
1) User A make a request > request will be store into a queue job
2) User B make a request > request will be store into a queue job
3) The queue job will send the first request to the wins form. Once first request is complete, then will follow by the second request
So my question is, this queue job should be develop inside the web application? Or it should be develop in a stand alone wins form?
Any example code for create a queue job in ASP.NET?
Or anyone can suggest a better solution?
using System.Collections.Generic;
Queue<task> Q = new Queue<task>();
public void Proccess_Request(string info)
{
task t = new task();
t.INFO = info;
Q.Enqueue(task);
}
public void DoWork()
{
//
while (Q.Count > 0)
{
task t = Q.Dequeue();
//Process task t
}
}
public class task
{
public string INFO { get; set; }
// Whatever task properties you need
}
You will need to build the service that accepts form data and passes it to method Process_Request. You will also need to call method DoWork either once every x minutes, or have it listen for Process_Request to fire.
Or you can use MSMQ and do it that way. the ASP.NET site sends a message to the queue, the winforms app (or service) is bound to the queue so when messages come into the queue, it will pick it up, process it and let it be done until no more messages in the queue.
You can handle cross domain queue communication with MSMQ, for example.
Related
I have a web API over net core 3.0 and my API is using a mail DLL where I do some operations.
Web API controller:
_mailService.SendEmail();
Mail DLL:
public void SendEmail()
{
Console.Writeline("Registering at database");
RegisterAtDatabase(); //Do some stuff at database
SendMailToUser(); //Send mail to user. His operation takes about 1 minute
Console.Writeline("End mail proccess");
}
private void SendMailToUser()
{
Console.Writeline("Creating and sending mail");
//Here some stuff to send the mail. It takes about 1 minute
Console.Writeline("Mail sended");
}
I want to call _mailService.SendEmail() and not wait for the whole process. I want to write at the database and not wait for email sending process. So console output should be....
Registering at database
Creating and sending mail
End mail proccess
//After 1 minute
Mail sended
Is that possible using Task Async and await in some way?
I wanna return the control to the API while the email is sending.
Thanks
Is that possible using Task Async and await in some way?
No, that's not what async is for.
The proper solution is to write the work (e.g., "send this message to this email address") to a reliable queue (e.g., Azure Queue / Amazon SQS / etc), and then have a separate background process read and process that queue (e.g., ASP.NET Core background service / Azure Function / Amazon Lambda / etc).
You can use background Task queue for this kind of works and run them in the background.
full info at Microsoft Documents Background tasks with hosted services in ASP.NET Core
I am using 1.5.6.RELEASE to create REST Api that shall store user actions in MS SQLServer database. To make this user action service asynchronous, I have configured #EnableAsync in my main class.
#EnableAsync
public class WebApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(WebApp.class, args);
}
}
#Async
public void saveAction(ActionInfo event) {
actionDataService.save(event);
}
I want to ensure that whatever happens(Server crashes, database goes down etc), user action posted by the client through Rest API service must be saved in database (may be through retry when database comes online or Application server starts again).
Proposed Solutions
Followings are the solutions:
1) Write AsyncUncaughtExceptionHandler to handle exceptions that retries again to save user action. But if Server crashes, the user action objects shall be lost.
2) Use JMS queues to store user action. If Server crashes, the JMS queue should not be lost. It must be able to retry it when server restores. (Just an idea, does not have much knowledge about queues)
Can you please suggest?
I have a signal r application. I have an issue of concurrent connection maxing out on iis. To avoid that i want my hub to send notification to groups created by in pack of 25 with delay of suppose 500ms. I add users to group as they connect. After count of 25 i add them to next group.Need help with how shall i send notification to each group with delay of 500ms.
I have looped through the number of groups and used
Thread.Sleep(500);
but all connected users do not receive the notification
Your question almost describes the solution - buffer the notifications fro 500ms then send an array of all of them.
You could do that by pushing the notification in a queue or list and and use a timer to send the notifications every 500ms.
A far better solution though would be to use Reactive Extensions and the Observable.Buffer(Timespan) method, thus avoiding queues and timers.
Subject<string> _subject;
.....
public void InitSubject()
{
_subject=new Subject<string>();
_subject.Buffer(Timespan.FromMilliseconds(500))
.Subscribe(notifications=>SendBatch(notifications));
}
....
public void SendBatch(IList<string> notifications)
{
//Get hold of the SignalR context and send the notifications here
}
public void QueueNotification(string notification)
{
_subject.OnNext(notification);
}
Buffer also allows you to batch a specific number of notifications, or use both a timespan and item limit to send a batch whenever one of the limits is reached.
Your code should call QueueNotification instead of sending the notification directly. Reactive Extensions also provide LINQ extensions, so you could apply filtering with the Where() method, eg to use different delays for different user groups, bypass buffering completely, or use any other combination.
You should note that since a Hub is transient, you can't put your subject inside the hub, although you can put QueueNotification in there, provided you provide a reference to the subject somewhere, eg by using Dependency injection to initialize the hub
I have to solve the following problem. We got an ASMX web service which is requested every two minutes. If this service is not requested for ten minutes an email should be sent. We want to realize this by using the scheduled tasks. We imagined it like this
1. Creating a scheduled task which will send an email every ten minutes
2. If the service is requested the execution time for the task will be set to ten minutes from now and so the execution time cannot be reached
- If the service is not requested the execution time will be reached and the email is sent
Is there a way to solve this in ASP.NET or are there maybe better solutions?
Thanks for any response.
You may want to take a look at the Revalee open source project.
You can use it to schedule web callbacks at specific times. In your case, you could schedule a web callback (10 minutes in the future) every time your web service is used. When your web service receives the callback, it can determine whether or not the service has been used recently. If the web service has been active, then the callback is ignored; if the web service has been inactive, then it can send out an email message.
For example using Revalee, you might:
Register a future (10 minutes from now) callback when your application launches.
private DateTimeOffet? lastActive = null;
private void ScheduleTenMinuteCallback()
{
// Schedule your callback 10 minutes from now
DateTimeOffset callbackTime = DateTimeOffset.Now.AddMinutes(10.0);
// Your web service's Uri
Uri callbackUrl = new Uri("http://yourwebservice.com/ScheduledCallback/YourActivityMonitor");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
Anytime your web service is used, you register another callback and store the date & time that your service was active as a global value.
lastActive = DateTimeOffset.Now;
ScheduleTenMinuteCallback();
Finally, when the web schedule task activates and calls your application back, then you test the value of the global
private void YourActivityMonitor()
{
if (!lastActive.HasValue || lastActive.Value <= DateTimeOffset.Now.AddMinutes(-10.0))
{
// Send your "10 minutes has elapsed" email message
}
}
I hope this helps.
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.
is it possible to stop a web service from executing?
I have a flex web application that searches clients with both full name and client id, when searching by name sometimes the usuer just types the last name and it takes a long time.
Since the app is used when clients are waiting in line, I would like to be able to stop the search and use their full name or id instead, and avoid waiting for the results and then having to search the user manually within the results.
thanks
edit: Sorry, I didn't explain myself correctly, when I meant "web service" I actually meant mx.rpc.soap.mxml.WebService, I want to stop it from waiting for the result event and the fault event. thanks.
There is actually a cancel(..) method explicitly for this purpose, though it is a little burried. Using the cancel method will cause the result and fault handlers not to be called and will also remove the busy cursor etc.
Depending on how you run your searches (ie. separate worker process etc), it is also possible to extend this by added in a cancelSearch() web service method to kill these worker processes and free up server resources etc.
private var _searchToken:AsyncToken;
public function doSearch(query:String):void
{
_searchToken = this.searchService.doSearch(query);
}
protected function doSearch_resultHandler(event:ResultEvent):void
{
trace("doSearch result");
trace("TODO: Do stuff with results");
_searchToken = null;
}
protected function doSearch_faultHandler(event:FaultEvent):void
{
trace("doSearch fault: " + event.fault);
_searchToken = null;
}
public function cancelSearch():void
{
var searchMessageId:String = _searchToken.message.messageId;
// Cancels the last service invocation or an invokation with the
// specified ID. Even though the network operation may still
// continue, no result or fault event is dispatched.
searchService.getOperation("doSearch").cancel(searchMessageId);
_searchToken = null;
trace("The search was cancelled, result/fault handlers not called");
// TODO: If your web service search method is using worker processes
// to do a search and is likely to continue processing for some time,
// you may want to implement a 'cancel()' method on the web service
// to stop any search threads that may be running.
}
Update
You could use disconnect() to remove any pending request responders, but it also disconnects the service's connection. Then call initialize().
/Update
You cannot stop the web service from executing, because that's beyond the Flex app's control, but you can limit the processing of the web service's response. For instance on the app, have a button like Cancel Search which sets a boolean bSearchCanceled to true.
The result handler for the web service call checks bSearchCanceled; if true just return.