protected void Button1_OnClick(object sender, EventArgs e)
{
FineTuneDB();// Long Task running in db
SendSMStoAllClients();// Using Twolio API to send sms to all client long task
lblText.Text = "Button click is completed our system threads working on your request";
}
Is this possible that on button click I can response to client and independent long task going on separately.
If you don't care about whether task is completed or not, you call FineTuneDB method like this.
Action fineTuneDB = FineTuneDB;
fineTuneDB.BeginInvoke(null, null);
Asynchronous Method Invocation
Updated:
Action<int, string> fineTuneDB = FineTuneDB;
fineTuneDB.BeginInvoke((int)Session["id"],
Session["name"].ToString(), null, null);
// Your method will be like this
public void FineTuneDB(int id, string)
{
}
Related
I try to build notifications for dashboard in my WebForms application under .NET 4. I have downloaded SignalR version 1.2 (both .net client and server) and prepared a simple notification example. Unfortunatelly it does not work and I can't figure why. If I type http://myserver.com/notificationSample/signalr/hubs javascript proxy appears and it looks ok.
Take a look at the implementation below, does someone see any bug?
a) Hub implementation
[HubName("NewMessage")]
public class NewMessageNotifier : Hub
{
public void NotifyDashboards()
{
Clients.All.NewMessageCreated();
}
}
b) Notification caller (server) ~/Pages/NotificationCaller.aspx
public partial class NotificationCaller : Page
{
private HubConnection connection;
private IHubProxy proxy;
protected void Page_Load(object sender, EventArgs e)
{
connection = new HubConnection( "http://myserver.com/notificationSample" );
proxy = connection.CreateHubProxy( "NewMessage" );
connection.Start().Wait();
}
// it is handler for onclick event on Button control
protected void NotifyDashboard(object sender, EventArgs e)
{
proxy.Invoke( "NotifyDashboards" ).Wait();
}
}
c) Dashboard (client, listener) ~/Pages/Dashboard.aspx
public partial class Dashboard: BasePage
{
private HubConnection connection;
protected void Page_Load(object sender, EventArgs e)
{
connection = new HubConnection( "http://myserver.com/notificationSample" );
var proxy = connection.CreateHubProxy("NewMessage");
proxy.On("NewMessageCreated", ShowNotification);
connection.Start();
}
private void ShowNotification()
{
ShowAlert("New message added!");
}
}
you are using it in the wrong way
First
both b and c are clients, the server gets started by itself, all you need is to do is to add
RouteTable.Routes.MapHubs();
to the
Application_Start
method in global.asax
Second
if you are going to use a webpage as the client, you should do it from javascript, as what you are doing now will not work because the
connection.Start()
is async and the request will end before it does anything, and it will not wait for incoming connections because all will be disposed
Now how to do it? it will take many pages here, so here are a few links
A Simple Tutorial
The Hubs Server API
The Hubs JavaScript API
and in case you missed it, a video that explains what is SignalR, how it works and a simple app which you can find here
We have a website that runs on ASP.NET. I would like to run a service that checks the database table every XX hours and do an action ( send mail ) if some conditions are not met.
We cannot use
Windows Service as the hosted server is not a dedicated server. (We just have the control panel)
SQL Service for sending mail as we are using Access 2003 (mdb) as our database. It resides at App_Data
IIS is also not available
Its very critical that we need some kind of polling in the server.
We are kind of stuck now. What are the alternatives we have?
its mentioned here
Easy Background Tasks in ASP.NET
here are some snippets from that link
private static CacheItemRemovedCallback OnCacheRemove = null;
protected void Application_Start(object sender, EventArgs e)
{
AddTask("DoStuff", 60);
}
private void AddTask(string name, int seconds)
{
OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(name, seconds, null,
DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, OnCacheRemove);
}
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
// do stuff here if it matches our taskname, like WebRequest
// re-add our task so it recurs
AddTask(k, Convert.ToInt32(v));
}
Works well in my testing; badges are awarded every 60 seconds like clockwork for all >users - Jeff Atwood
There's a trick you can use to simulate a windows service using just your ASP.NET web service.
The gist of it goes as follows:
Place an item in your cache with an expiry period that is equal to how often you would like to poll your database.
Add a callback that is fired when the item is removed from the cache. In the callback method, add your polling code to do the thing you want to do (call access database, send mails, etc.)
so: in your global asax, something like this:
private const string DummyCacheItemKey = "pollingCacheKey";
protected void Application_Start(Object sender, EventArgs e)
{
RegisterCacheEntry();
}
private bool RegisterCacheEntry()
{
if( null != HttpContext.Current.Cache[ DummyCacheItemKey ] ) return false;
HttpContext.Current.Cache.Add( DummyCacheItemKey, "Test", null,
DateTime.MaxValue, TimeSpan.FromMinutes(1),
CacheItemPriority.Normal,
new CacheItemRemovedCallback( CacheItemRemovedCallback ) );
return true;
}
public void CacheItemRemovedCallback( string key,
object value, CacheItemRemovedReason reason)
{
Debug.WriteLine("Cache item callback: " + DateTime.Now.ToString() );
// Do the service works
DoWork();
ReregisterCacheItem();
}
Whilst it's not ideal, it fits your constraints.
Full details of the technique can be found here: http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc
Ok, I've poked around and can't find a suitable answer to my question. I have a rather complicated code base that uses a Timer to initiate the creation of background worker to transmit something on regular intervals.
I am running into an issue when it calls ReportProgress:
"This operation has already had OperationCompleted called on it and further calls are illegal."
Stack Trace:
at System.ComponentModel.AsyncOperation.VerifyNotCompleted()
at System.ComponentModel.AsyncOperation.Post(SendOrPostCallback d, Object arg)
at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress, Object userState)
at NAME.TX.Work(Object sender, DoWorkEventArgs e) in file.cs:line 68
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
My question is relatively simple, the function called when the timer goes off creates a new background worker, but is it actually a new background worker?
My code (simplified because its very bulky):
//THIS IS THE FUNCTION CALLED BY TIMER
public void TransmitMSG(MSG msg)
{
//Initialze _tx
this.m_thread = new BackgroundWorker();
m_thread.WorkerReportsProgress = true;
//Initialize all events used by _tx
m_thread.DoWork += new DoWorkEventHandler(this.Work);
m_thread.ProgressChanged += new ProgressChangedEventHandler(this.Report);
m_thread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.Complete);
//Run the backgroundworker
m_thread.RunWorkerAsync(msg);
}
//THIS IS THE WORK FUNCTION
public override void Work(object sender, DoWorkEventArgs e)
{
//This code is in the TX Thread
//The sender should be the a BackgroundWorker
BackgroundWorker _tx = sender as BackgroundWorker;
//Check the Argument
if (e.Argument != null && e.Argument.GetType() == typeof(MSG))
{
//Transmit the Argument Message
m_THING.Transmit((MSG)e.MSG)
//Report progress according to the result
_tx.ReportProgress(CONSTANTS.PROGRESS.SUCCESS_TX, (MSG)e.Argument);
}
}
The Work function is an override because there is a higher handling class that allows for transmit and recieve, these two inherit from the same class so I can have common ReportProgress and Close methods.
Can someone provide me with a simple example of Asynchronous page processing in ASP.NET Webforms 2.0 (I'm using VS 2010, so new syntax like lambdas are ok)?
I have some long running requests that I don't want tying up IIS threads.
For simplicity's sake, let's say my current code looks like this:
protected void Page_Load(object sender, EventArgs e)
{
string param1 = _txtParam1.Text;
string param2 = _txtParam2.Text;
//This takes a long time (relative to a web request)
List<MyEntity> entities = _myRepository.GetEntities(param1, param2);
//Conceptually, I would like IIS to bring up a new thread here so that I can
//display the data after it has come back.
DoStuffWithEntities(entities);
}
How can I modify this code so that it is asynchronous? Let's assume that I already set async="true" in the aspx page.
EDIT
I think I figured out how to get what I'm looking for. I've put the example code in an answer here. Feel free to point out any flaws or changes that can be made.
I asked some folks on the ASP.NET team. Here's their emailed response to me, and now, to you.
All that code ends up doing is spinning up a new thread and performing delegate invocation on that thread. So now there are two threads running: the request thread and the new thread. Hence this sample actually has worse performance than the original synchronous code would have had.
See http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45 for a sample on how to write and consume async methods in ASP.NET.
Here is a simple example of asynchronous processing.
protected void Page_Load(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
ThreadPool.QueueUserWorkItem(state => Dokimes_Programming_multithread_QueryWorkThead.ThreadProc2());
Debug.Write("Main thread does some work, then sleeps.");
// If you comment out the Sleep, the main thread exits before
// the thread pool task runs. The thread pool uses background
// threads, which do not keep the application running. (This
// is a simple example of a race condition.)
// Thread.Sleep(4000);
txtDebug.Text += "ended";
Debug.Write("end.");
}
// This thread procedure performs the task.
static void ThreadProc(Object stateInfo)
{
// No state object was passed to QueueUserWorkItem, so stateInfo is null.
Debug.Write(" Hello from the thread pool 1.");
}
static void ThreadProc2()
{
// No state object was passed to QueueUserWorkItem, so stateInfo is null.
Debug.Write("Hello from the thread pool 2.");
}
Other way
You can use the PageAsyncTask, see here a full example:
http://msdn.microsoft.com/en-us/library/system.web.ui.pageasynctask.aspx
Something like
clAsynCustomObject oAsynRun = new clAsynCustomObject();
PageAsyncTask asyncTask = new PageAsyncTask(oAsynRun.OnBegin, oAsynRun.OnEnd, oAsynRun.OnTimeout, null, true);
Page.RegisterAsyncTask(asyncTask);
Page.ExecuteRegisteredAsyncTasks();
I think I discovered how to do what I wanted to accomplish... though it may not be the best way, feel free to chime in.
At the time of writing there was only one answer in this thread, by Aristos. While he gave an example of executing an asynchronous request, what I wanted was a way to tell ASP.NET to execute some long running method, release the IIS thread so it can be available to service other requests, and then come back when the method finished.
Here's what I came up with, using the same (or similar) example in the question:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Web.UI;
namespace WebApplication2
{
public class MyEntity
{
public string Name { get; set; }
}
public class MyRepository
{
public List<MyEntity> GetEntities(string param1, string param2)
{
Thread.Sleep(10000);
return new List<MyEntity> {new MyEntity {Name = "John Smith"}};
}
}
public partial class Default : Page
{
private readonly MyRepository _myRepository = new MyRepository();
private List<MyEntity> _myEntities;
protected void Page_Load(object sender, EventArgs e)
{
}
private void DoStuffWithEntities()
{
Response.Write("<br/><br/><b>" + _myEntities[0].Name + "</b><br/><br/>");
}
protected void _btnProcess_Click(object sender, EventArgs e)
{
AddOnPreRenderCompleteAsync(BeginExecution, EndExecution, null);
}
private void GetEntities()
{
string param1 = _txtParam1.Text;
string param2 = _txtParam2.Text;
//This takes a long time (relative to a web request)
_myEntities = _myRepository.GetEntities(param1, param2);
}
private IAsyncResult BeginExecution(object sender, EventArgs e, AsyncCallback callback, object state)
{
var t = new ThreadStart(GetEntities);
return t.BeginInvoke(callback, null);
}
private void EndExecution(IAsyncResult result)
{
//Conceptually, I would like IIS to bring up a new thread here so that I can
//display the data after it has come back.
DoStuffWithEntities();
}
}
}
I'm writing an ASP.NET application. When a specific kind of request is being handled, I want to schedule a method to be called in a certain number of minutes after the request is handled. The postponed method does not need to communicate with the client that made the original request, it is just intended to do some "housekeeping" work. What is the best way to do this in an ASP.NET context? (It's ok to not fire the event if the application domain dies for some reason).
In Global.asax use this to check your incoming request:
protected void Application_BeginRequest(object sender, EventArgs e)
{
CheckRequest(HttpContext.Current.Request);
}
if your request is valid, register a cache entry:
private void CheckRequest(HttpRequest request)
{
if (request)
RegisterCacheEntry();
}
private void RegisterCacheEntry()
{
if (HttpRuntime.Cache[CacheItemKey] == null)
{
HttpRuntime.Cache.Add(CacheItemKey, "your key", null,
DateTime.Now.AddSeconds(60), //change to fire in whatever time frame you require
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(CacheItemRemovedCallback));
}
}
then process your function in the callback:
private void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
// execute your function
}
You could start a timer (System.Timers.Timer) from one of the application event in global.asax.cs (e.g. in Application_BeginRequest) after checking that it is required for that request.
Then, in the handler of the timer's Elapsed event, make sure that you stop the timer.
E.g. put something like this into global.asax.cs:
System.Timers.Timer _timer = null;
void Application_BeginRequest(object sender, EventArgs e)
{
// check if cleanup must be initiated
bool mustInitCleanup = RequestRequiresCleanup();
if ((_timer == null) && mustInitCleanup)
{
_timer = new System.Timers.Timer(5000);
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
}
}
void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_timer.Stop();
_timer = null;
// do cleanup task
}
Simply create a new thread to do the housekeeping work and at its beginning have it sleep for however long you want the server to wait before doing the action.
For example, somewhere in that specific request you want to call DoSomething:
aNewThread = new Thread(Foo);
aNewThread.Start();
public void Foo()
{
Thread.Sleep(5000);
DoSomething();
}