when i am doing long running task then i want to show busy image and hide the busy image when job done.
private void btnSave_Click(object sender, EventArgs e)
{
string strRating = "";
Messages oErrMsg = Messages.Instance;
FeedBack oFeedBack = new FeedBack();
picbox.Visible = true;
Application.DoEvents();
if (cboRating.Text.Trim() == "--Select--")
{
strRating = "";
}
else
{
strRating = cboRating.Text.Trim();
}
try
{
oErrMsg = oFeedBack.UpdateFeedBack(JobID, strRating, txtComments.Text.Trim(), AccountRef, PartNumber);
if (!oErrMsg.IsError)
{
picbox.Visible = false;
comments _cmm = new comments();
_cmm.Comments = txtComments.Text;
_cmm.Rating = strRating;
_cmm.Row = this.Row;
_cmm.Col = this.Col;
OnValueChanged(_cmm);
DialogResult = DialogResult.OK;
this.Close();
}
else
{
picbox.Visible = false;
MessageBox.Show(oErrMsg.Message);
}
}
catch (Exception ex)
{
picbox.Visible = false;
MessageBox.Show(ex.Message.ToString());
}
}
picbox.Visible = true;
picbox has busy image but the problem is image is not showing because i am show busy and then a long running operation start. so guide me how could i show the busy image asynchronously and hide when job done. thanks
As suggested by #Piotr, you can make use of BackgroundWorker thread to achieve this.
As a reasoning why your code is not working, the btn click handler runs on UI thread and you happen to be doing all the work in the same (UI) thread which mean UI thread doesn't get to paint changes in Busy Indicator.
while Application.DoEvents() helps in a force repaint, it should be avoided and the right way to achieve this is delegating all work to a background thread (you can also use ThreadPool.QueueUserWorkItem) and marshal all changes to UI object/properties to UI thread by using Control.BeginInvoke/Control.Invoke.
Since, any changes to a UI object could only be done on a UI thread you will have to marshal such updates by using Control.Invoke etc.
BackgrounWorker class encapsulates this marshalling by providing differenet event handlers. From memory, I thin ProgressChanged and Completed handlers are invoke on UI thread. So you can safely update your UI control within these handlers and do the time consuming work in DoWork handler.
Update: Here is good explanation on why DoEvents is Evil.
Thomas,
please consider using a BackgroundWorker (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.80).aspx).
It's been present in the .NET framework since the version 2.0.
Related
I have been trying to implement an event driven push to a client browser. I am using ReactiveX to produce the async task from the events but I can't even get my HttpHandlers to output their response.
I have tried with a simple HttpHandler:
public class Handler2 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/event-stream";
HttpResponse response = context.Response;
DateTime startdate = DateTime.Now;
while (startdate.AddMinutes(10) > DateTime.Now)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string responseText = DateTime.Now.TimeOfDay.ToString();
response.Write(string.Format("data: {0}",js.Serialize(responseText)));
response.Flush();
System.Threading.Thread.Sleep(1000);
}
response.Close();
}
public bool IsReusable
{
get
{
return false;
}
}
}
with the following client side code:
function initialize() {
if (window.EventSource == undefined) {
document.getElementById('targetDiv').innerHTML = "Your browser doesn't support Server Side Events.";
return;
}
var source = new EventSource('Handler2.ashx');
source.onopen = function (event) {
document.getElementById('targetDiv').innerHTML += 'Connection Opened.<br>';
};
source.onerror = function (event) {
if (event.eventPhase == EventSource.CLOSED) {
document.getElementById('targetDiv').innerHTML += 'Connection Closed.<br>';
}
};
source.onmessage = function (event) {
document.getElementById('targetDiv').innerHTML += event.data + '<br>';
};
}
I have more a more complex HttpTaskAsyncHandler ready to hook up, but I can't even get this working >_<
I get the Connection Opened message, Handler2.ashx appears to remain connected (Looking at Chrome dev tools / Network).
I am, on the other hand, getting some data from a SignalR connection?
"ws://localhost:50022/ed4b66c7eb394a8789b5f6a631f4ff09/arterySignalR/connect?.."
Have I set it up wrong?
As far as I've seen on other examples, this code should be working as-is. Please could anyone help me. I just want a simple SSE control that I can trigger from server side events.
Thanks in advance
I had given this answer before, but let me elaborate:
Looking at the Network tab in Google Chrome developer tools reveals quite a lot from your http://live.meetscoresonline.com/test-sse.aspx
There are no SSE being generated at all - to see this click on the Others button under Network, this is where you would normally be able to track the SSE data stream
I use the following code in my SSE's with a simple HTTPListener and it works well without the delays you mentioned, and always shows up correctly across browsers when using this polyfill
res.AddHeader("Content-Type", "text/event-stream")
res.AddHeader("Cache-Control", "no-cache")
res.AddHeader("Access-Control-Allow-Origin", "*")
res.KeepAlive = True
I am developing ASP.NET Application using c#.net. In that i wrote code for sending a single mail to multiple Mail-Id's .
Hear i used For-loop for continues sending mail.
So, Hear my question is,
1. I want to stop or pause sending mails , when i click "stop" button ???.
2. Is it possible to kill or pause the process of continues sending mails. ???
for (int i = 0; i < B.Length; i++)
{
if (txt_To.Text == "")
{
txt_To.Text = B[i].ToString();
Methord1(); ////////////// UID ,PWD code
int k = i + 1;
Session["num"] = k;
txt_To.Text = "";
Label4.Text = Session["NUM"].ToString() + "Mail sent ...";
}
}
If I am understanding your question correctly you have an emailing process you have started in a thread, and you want to be able to terminate the thread when a stop button is clicked. Is that correct?
The correct way to do this is to create a flag you can set on the threaded class to 'ask' it to terminate - force terminating a thread is a terrible terrible thing.
So, using your existing method I have added a bool in that determines whether the thread keeps executing. You will also need a bool in your class definition that runs all this code:
private volatile bool KeepRunning = true;
public void SendEmails()
{
for (int i = 0; i < B.Length; i++)
{
if (!KeepRunning) return; //<--- this is the new line
if (txt_To.Text == "")
{
txt_To.Text = B[i].ToString();
Methord1(); ////////////// UID ,PWD code
int k = i + 1;
Session["num"] = k;
txt_To.Text = "";
Label4.Text = Session["NUM"].ToString() + "Mail sent ...";
}
}
}
To be able to access the KeepRunning variable it needs to be marked as volatile to indicate you will access it from multiple threads. Now you can invoke the SendEmails() method in a separate thread, and you have a way of asking it to stop later on. T
If that is the case then you will need to retain a reference to the thread you have started the process in:
Thread MyThread = new Thread(new ThreadStart("SendEmails"));
MyThread.Start();
Now the thread is running and looping.
To terminate the thread (in your 'stop' button handler or whatever) you just set KeepRunning as false, and the next time the loop executes it will drop out naturally on that line. You should also wait for the worker thread to rejoin the main thread before continuing:
KeepRunning = false;
MyThread.Join();
Please note this is all example code and hasn't been tested.
In an MVC web application I use the SpeechSynthesizer class to speak some text to a .wav file during a function called by a controller action handler that returns a view. The code executes, writes the file, and the action handle returns, but the development server usually, but not always, never comes back with the return page. This is the text-to-speech code:
string threadMessage = null;
bool returnValue = true;
var t = new System.Threading.Thread(() =>
{
try
{
SpeechEngine.SetOutputToWaveFile(wavFilePath);
SpeechEngine.Speak(text);
SpeechEngine.SetOutputToNull();
}
catch (Exception exception)
{
threadMessage = "Error doing text to speech to file: " + exception.Message;
returnValue = false;
}
});
t.Start();
t.Join();
if (!returnValue)
{
message = threadMessage;
return returnValue;
}
I saw a couple of posts for a similar problem in a service that advised doing the operation in a thread, hence the above thread.
Actually, using the SpeechSynthesizer for other things can hang as well. I had a page that just enumerated the voices, but it would get stuck as well. Since there is no user code in any of the threads if I pause the debugger, I have no clue how to debug it.
I've tried Dispose'ing the SpeechSynthesizer object afterwards, calling SetOutputToDefaultVoice, to no avail. I've tried it on both Windows 8.1 and Windows 8, running with the development server under the debugger, or running IIS Express separately.
Any ideas? Is there other information I could give that would be helpful?
Thanks.
-John
Try
Public void Speak(string wavFilePath, string text)
{
using (var synthesizer = new SpeechSynthesizer())
{
synthesizer.SetOutputToWaveFile(wavFilePath);
synthesizer.Speak(text);
return outputFile;
}
}
Task.Run(() => Speak("path", "text")).Result;
It worked for me in IIS Express
I have a scenario where i have a page which opens a dialog on click of a button, in the opened dialog form on button click i can read a list of data from a selected .txt file and build a query and add the data to some database tables. Since there could be large amount of data this process can take large time because of this the user would not be able to work on the application until the upload completes. Hence to make the upload process Asynk i am using the PageAsyncTask. Below is the code sample, but in the method called in the PageAsyncTask the HttpContext.Current is null hence i am not able to use session handling. Please any guidance on this why would this be null and how can i use the session in this case
protected void BtnUpload_click(object sender, EventArgs e)
{
PageAsyncTask asyncTask1 = new PageAsyncTask(OnBegin, OnEnd, OnTimeout, SessionManager.UserData, true);
Page.RegisterAsyncTask(asyncTask1);
Page.ExecuteRegisteredAsyncTasks();
}
public IAsyncResult OnBegin(object sender, EventArgs e,
AsyncCallback cb, object extraData)
{
_taskprogress = "AsyncTask started at: " + DateTime.Now + ". ";
uData = extraData as UserData;
_dlgt = new AsyncTaskDelegate(BeginInvokeUpload);
IAsyncResult result = _dlgt.BeginInvoke(cb, extraData);
return result;
}
private void BeginInvokeUpload()
{
string selectedFileName = string.Empty;
string returnValuePage = string.Empty;
User teller = new User();
SessionManager.UserData = uData;
}
private void BeginInvokeUpload()
{
string selectedFileName = string.Empty;
string returnValuePage = string.Empty;
User teller = new User();
SessionManager.UserData = uData;
}
public class SessionManager
{
public static UserData UserData
{
get
{
UserData userData = null;
if (HttpContext.Current.Session["UserData"] != null)
{
userData = HttpContext.Current.Session["UserData"] as UserData;
}
return userData;
}
set
{
HttpContext.Current.Session["UserData"]=value;
}
}
}
The answer is simple : you can not use the session if the HttpContext.Current is null
So if you need to modify the session you simple can not and the only alternative is to make your totally custom session module/solution.
If you only need to read some values, then you can pass them when you create your thread.
And finally the only solution is to not use the thread if you won to manipulate the session variables.
why this design?
why MS session did not allow you to handle it out side of a page and inside a thread ? the answer is because is need to lock the session data on page processing - with this lock even if you start a thread and been able to get the session data, will not been able to use it parallel.
Also if you been able to use the session your self in a thread, then this thread may lock the entire page view process, because I say it again, session is lock the entire page view, and each page that use the same session are not work in parallel
This lock of session on the entire page is necessary the way the MS session works, and the only way to avoid that is to make a totally custom session solution, and handle special cases with different code.
The good about that design is that you avoid to make a lot of locking and synchronization by your self on every page call - for example if you disable the session on a page, and use that page for data inserting, if a use make multiple double clicks on the insert, and you do not handle it with synchronization on the insert, you end up with multiple same insertions.
More about session lock:
Replacing ASP.Net's session entirely
Web app blocked while processing another web app on sharing same session
jQuery Ajax calls to web service seem to be synchronous
ASP.NET Server does not process pages asynchronously
Similar question:
How to get Session Data with out having HttpContext.Current, by SessionID
I have a site I manage for a client and they wanted to be able to send out emails to all of their membership. I contacted the host and they suggested writing it in a way that it sends out in batches of 50 or less every minute so the mail server doesn't get overloaded.
That sounds great but the only way I could think of to do this without causing the administrator to have to sit on a page while it sends emails and reloads between each batch was to have a page call an ashx handler which fired up a thread to do the work and the thread is set to sleep after each batch for 60 seconds.
When I run the code from my machine it works fine and completes the entire list of emails. When I run it from the web host, which I don't have access to aside from ftp, it nearly completes but doesn't. Then if I try to hit the ashx page again to finish any that weren't sent, it doesn't do anything. It's like the thread causes something to lock up maybe and keeps additional threads from running.
Here's the code I'm using and I've never used threading before... so, does anyone know why it might be doing this and how to make it work correctly? Do I need to specifically kill the thread after I'm done? If so, how? Thanks.
public void ProcessRequest(HttpContext context)
{
if (context.Request.QueryString["id"].IsValid<int>())
{
campaignId = context.Request.QueryString["id"].To<int>();
var t = new Thread(new ThreadStart(SendEmails))
{
Priority = ThreadPriority.Lowest
};
t.Start();
}
}
private void SendEmails()
{
int currentCount = 0;
BroadcastEmailCampaign campaign = EmailController.GetCampaign(campaignId, false);
List<Member> memberlist = EmailController.GetEmailList(campaign.CampaignId);
var message = new MailMessage
{
Body = campaign.Body,
From = new MailAddress(campaign.SentBy),
IsBodyHtml = true,
Subject = campaign.Subject,
BodyEncoding = Encoding.UTF8
};
//add attachment
if (!string.IsNullOrEmpty(campaign.Attachment) && File.Exists(campaign.Attachment))
{
var attachment = new Attachment(campaign.Attachment);
EmailAttachmentType.SetContentProperites(campaign.Attachment, ref attachment);
message.Attachments.Add(attachment);
}
if (memberlist.Count <= 0)
{
return;
}
bool sendingComplete = false;
EmailController.SetCampaignSendingStatus(true, campaign.CampaignId);
while (sendingComplete == false)
{
message.Bcc.Clear();
message.To.Clear();
message.To.Add(new MailAddress(dummyEmailAddress));
List<Member> emailsToSend = memberlist.Skip(currentCount).Take(takeCount).ToList();
if (emailsToSend.Count <= 0)
{
sendingComplete = true;
EmailController.LogEmailCampaignResult(campaign);
EmailController.SetCampaignSendingStatus(false, campaign.CampaignId);
}
if (!sendingComplete)
{
foreach (Member email in emailsToSend)
{
message.Bcc.Add(new MailAddress(email.Email));
campaign.SentTo.Add(new BroadcastEmailCampaignSentTo
{
MemberId = email.MemberId,
Email = email.Email,
DateSent = DateTime.Now
});
}
EmailController.SendEmail(message);
EmailController.LogEmailsSent(emailsToSend, campaignId);
currentCount += takeCount;
Thread.Sleep(pauseTime);
}
}
}
Since I read a lot of threading in ASP.NET and still have no real clue of the dos and donts, I usually solve tasks like you describe by a console application that runs as a Scheduled Task in Windows Task Scheduler every e.g. 5 minutes:
In the ASP.NET page, I write all required information into a database table.
The scheduler periodically polls the database table for new jobs (e.g. sending of an e-mail) and processes, then empties the database table that serves as a queue.
This enables my application to stay responsive and in addition I don't have to worry that an IISRESET or something like this would kill my background threads.
t.IsBackground=true;
If that doesn't do it, I suggest using the ThreadPool with QueueUserWorkItem.