C# enabling menu item - c#

I have a try-catch statement in reference to downloading a file. When the file is downloaded, I then enable one of my menu items then turn off a timer set to retry the download in one minute.
My problem is that for some reason my trafficManagementToolStripMenuItem.Enabled = true; line is activating the catch statement even though the menu item is being enabled. The file correctly downloads and when I comment out that line, it works perfectly. But every time I run it, I get the "error" message box and the timer is not disabled even though the menu item correctly enables after the download is complete.
Any ideas?
try
{
////downloads Data
string address = "http://website.file.txt";
string filename = "vsd.txt";
WebClient client = new WebClient();
client.DownloadFile(address, filename);
trafficManagementToolStripMenuItem.Enabled = true;
timer1.Enabled = false;
}
catch
{
timer1.Enabled = true;
MessageBox.Show("error", "test");
}

You don't say what the exception is, but I'd guess that you're running your download routine in a background thread, is that right? You can only access controls from the thread that created them: the main UI thread. Accessing a control such as a ToolStripMenuItem from a background thread will cause an exception.
If this is the case, use the Control.Invoke or Control.BeginInvoke method to run the .Enabled = true call on the ToolStripMenuItem's thread. To do this, you'll need a Control (unfortunately ToolStripMenuItem is only a Component). I'll assume you can get a reference to the containing Form from somewhere. Now you can write this:
Action enableAction = delegate() { trafficManagementToolStripMenuItem.Enabled = true; }
form.BeginInvoke(enableAction);
This causes the enableAction to run on the correct UI thread for form.

change your catch to be
catch (Exception ex)
{
timer1.Enabled = true;
MessageBox.Show("error", ex.Message);
}
This will at least give you the actual error message.
I'm guessing it's because you are not running in the UI thread and need to use Control.Invoke, take a look at http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx on msdn

Related

Code after task is not called

The scenario is that I have text box which I put there URL when the user
type the url and press go I call to the service in TPL ,when the service
is loaded I need to enable the next button(Im working on wizard) if I dont use TPL IsServicevalid get true(bind to command)and the next button is enabled .but in task(TPL) the data is loaded and the next is disabled (even if I put it in the continue) I have noticed that if I click on the page with the mouse anywhere the next turn to enable,do you face some issue like this before?
even if the next button is disabled and I click on it it turn to enable ,all of this happen
just when I use task ,any idea?
this is strange ...:(
Task.Factory
.StartNew(() =>
{
//-----get service Data ---------
try
{
GetUsersData();
}
catch (Exception e)
{
_isValid = false;
ThrowErrorMessage(e.Message);
}
})
.ContinueWith((task) =>
{
Mouse.OverrideCursor = null;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
isServiceValid = true;
Sometimes the CanExecute state of commands won't be reflected on the ui untill you click on it.
I don't know why this happens, I personally think this is a behavior that should be changed in the framework itself if possible.
However you can force an update by calling
System.Windows.Input.CommandManager.InvalidateRequerySuggested();

Show "please wait" message box

I want to show a 'please wait' message box while my main form is doing a lengthy task. As for my case, the lengthy task is transmitting serial protocol. Below is my code:
public void transmitprotocol()
{
try
{
MessageBox.Show("Please wait. Uploading logo.", "Status");
// Transmitting protocol coding here. Takes around 2 minutes to finish.
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
I've tried the above method using MessageBox like the above coding, but I always have to close the MessageBox only it will start transmitting protocol.
Is there any method I can do to still show the 'please wait' MessageBox while it transmit protocol?
You will need to do the expensive operation on a background thread. For that, use either a BackgroundWorker or the new Parallelization Library (.NET 4 and so on).
Actually you need to close the dialog because it blocks the execution until you, well, close it. What you do is that you start the operation, then show the dialog and then, once the operation is done, you close the dialog.
Now, if you're using WPF I will strongly suggest you to don't use a Dialog Box and instead use a Busy Indicator, it's free, pretty easy to use and not so ugly as the Message Box.
EDIT: Now that you specify you're using WinForms, then go ahead, implement the background worked and, why not, a transparent window without chrome whose purpose is to show a Busy label. Once the background worker ends you close that window.
You have to prepare a backgroundworker and use a windows form instead of MessageBox.
Something like this as simple as copy/paste:
Form1 msgForm;
public void transmitprotocol()
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
//you can use progresschange in order change waiting message while background working
msgForm = new Form1();//set lable and your waiting text in this form
try
{
bw.RunWorkerAsync();//this will run all Transmitting protocol coding at background thread
//MessageBox.Show("Please wait. Uploading logo.", "Status");
msgForm.ShowDialog();//use controlable form instead of poor MessageBox
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// Transmitting protocol coding here. Takes around 2 minutes to finish.
//you have to write down your Transmitting codes here
...
//The following code is just for loading time simulation and you can remove it later.
System.Threading.Thread.Sleep(5*1000); //this code take 5 seconds to be passed
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//all background work has complete and we are going to close the waiting message
msgForm.Close();
}
The easiest way to do this is to open the splash with show()
Open the desired form and pass it an instance of the splash form in the constructor:
Wait myWaitDialog = new Wait(); //Wait is your splash
myWaitDialog.Show();
myWaitDialog.Refresh(); //Otherwise screen fails to refresh splash
ScheduleClassForm myForm = new ScheduleClassForm(myWaitDialog);
myForm.TopLevel = true;
myForm.ShowDialog();
Add this code to your resulting form constructor:
public ScheduleClassForm(Form WaitWindow)
{
InitializeComponent();
WaitWindow.Close();
}
For me it failed in the form_load but worked in the constructor. Make sure your work is done (e.g. db load) prior to closing the WaitWindow.

Process.Start() and continue with my code

My program is in win forms (c#). It should open an external program, do a printscreen of it's main window, and close it.
By using Process.Start() I can open the the program, but then all the focus is on it and my code is halted. Only when I close it myself my form continues- but it's too late for the screenshot.
So how do I force my code to keep running?
public void Runttk(string maromnum)
{
Process runttk = new Process();
runttk.StartInfo.UseShellExecute = true;
runttk.StartInfo.FileName = #"C:\\program.exe";
runttk.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
runttk.Start();
this.Focus();
try
{
if (runttk.WaitForInputIdle()==true)
{
PringJpg(maromnum);
Killttk();
}
}
catch (Exception e)
{
}
}
Thank you
UPDATE:
eventuanlly I've used Thread.Sleep(3000). Crued but do the trick.
I didn't used backgroundworker because the sync between the finale uplaod the the extenral program and my code wasn't clear enough.
Trying your code, but with another program like notepad.exe, Notepad runs and then control drops through to where you call PringJpg.
So I think the problem is that it is blocking on if (runttk.WaitForInputIdle()==true), please try adding a timeout to this operation.
Maybe your programm is never idle - means that runttk.WaitForInputIdle()==true let your app wait until you close it.
Add a limit ( for example runttk.WaitForInputIdle(500)==true) should fulfill your needings.

Ticker generated forms not displaying correctly

Hopefully this isn't too difficult to follow.
I'm currently working on a small timelogging application that runs quietly in the background. Every time the ticker runs down, the application prompts the user to say what he/she was doing since the last prompt. I'll eventually have the application write the data into a spreadsheet.
One of the options I have so far enables the user to choose whether or not he/she would like to use the default prompting setting (every time a prompt is missed, it stays visible until the next one is created, meaning if the user leaves his/her computer for a while there may be a fair few prompts sitting on the screen waiting to be filled in) or would like to combine all the prompts (every time a prompt is missed and a new one pops up, the old one is closed and the new one covers the time of the old prompt and the new prompt).
The user can also select a tickbox to turn prompts off. When he/she turns prompts back on again, a prompt pops up asking the user to fill in what he/she was doing while prompts were turned off (useful when the user is running fullscreen applications, etc).
My problem is, when I try to generate the prompts, they don't display correctly. I can't manipulate them at all and none of the controls display. They basically look like empty forms.
Here's my code for generating prompts using the ticker:
public void ticker(object source, System.Timers.ElapsedEventArgs e)
{
if (groupMissed)
{
incrementsMissed += 1;
if (incrementsMissed > 1)
{
IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(delegate { form.Close(); }));
}
}
}
else
{
incrementsMissed = 1;
}
IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
theIncrementForm.Show();
latestIncrement = e.SignalTime;
}
And here's my code for generating prompts using the "turn prompts off" checkbox:
private void chkbxAlerts_Click(object sender, EventArgs e)
{
if (!chkbxAlerts.Checked)
{
// Ensures that the time missed is covered and restarts the timer
DateTime now;
now = DateTime.Now;
if ((now - latestIncrement).TotalMinutes >= 1) // Only records time if it is equal to or greater than one minute
{
// TO-DO: FIX
if (groupMissed)
{
incrementsMissed += 1;
if (incrementsMissed > 1)
{
IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(delegate { form.Close(); }));
}
}
}
else
{
incrementsMissed = 1;
}
IncrementForm theIncrementForm = new IncrementForm(this, now, latestIncrement);
theIncrementForm.Show();
latestIncrement = now;
}
timer.Enabled = true;
}
else
{
// Stops the timer
timer.Enabled = false;
}
}
If you need any further clarification, please let me know. Thanks so much in advance for any help, this has been bugging me.
System.Timers.Timer has a SynchronizingObject property. If you set that to the main form (or the form that contains the timer), then the timer tick event will be raised on the GUI thread.
Do note that System.Timers.Timer has the nasty habit of swallowing exceptions that occur in the Elapsed event. If your tick handler throws an exception, you'll never see it. It's a nasty bug hider. For that reason, I recommend using either System.Windows.Forms.Timer or System.Threading.Timer. If you use the Windows Forms timer, the elapsed event is raised on the GUI thread. If you use System.Threading.Timer, you'll have to use Invoke as NSGaga shows in his answer.
See Swallowing exceptions is hiding bugs for more information about why I discourage the use of System.Timers.Timer.
I think, from what I can see, not 100% but your timer is spawning your windows in a separate thread (being from the timer ticker call).
While theoretically that can work (take a look at this How to open a form in a thread and force it to stay open)
...you may be much better off staying within the main thread.
Try something like this...
yourMainWindow.Invoke(new MethodInvoker(() =>
{
IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
theIncrementForm.Show();
latestIncrement = e.SignalTime;
}));
...that's from your timer - that way (as I can see) you should have it all 'on the main thread' and make things much easier for you.
hope this helps

How to fix "The requested resource is in use. (Exception from HRESULT: 0x800700AA)"

How can I solve this error?
"The requested resource is in use. (Exception from HRESULT: 0x800700AA)".
This appears while navigating to a different website using the WebBrowser control in C# .NET. Why?
The WebBrowser control is considered "in use" if either a navigation action is currently being processed, or any blocking dialog from the control is currently open (including context menu, Javascript alerts, NTLM login dialog, etc.). You can use the WebBrowser.IsBusy property to detect these states.
If due to a currently incomplete navigation action, you could try to stop the current navigation (if you indeed want to stop when the page is not completed loaded) or add the new navigation to a request queue and use a timer to wait until WebBrowser.IsBusy returns false.
If instead the busy state is due to one or more open blocking dialogs, you could do the same wait technique and perhaps Messagebox.Show() the user a message that pending navigation is delayed due to an open dialog window.
I had this same issue. Calling WebBrowser.Stop() did not help, and WebBrowser.IsBusy never became false.
It turns out that if the page creates any sort of dialog (alert() popups, javascript errors, NTLM login popups etc.) you can't navigate away from the page until the dialog is closed.
My solution was to prevent the dialogs from showing in the first place. Apparently preventing all of these popups is simple; just set
webBrowser.ScriptErrorsSuppressed = true;
bool go = false;
string SiteContent1 = string.Empty;
string SiteContent2 = string.Empty;
int index = 0;
WebBrowser wb = new WebBrowser();
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
try
{
if (go)
{
SiteContent2 = wb.DocumentText;
// Code to compare to contents of the webbrowser
index++;
go = false;
steps = 1;
}
if (!go)
{
if (index >= TotalSiteCount)
{
Stop();
}
else if (steps == 1)
{
wb.Navigate(UrltocompareList[index].Url1);
}
else if (steps == 2)
{
SiteContent1 = wb.DocumentText;
wb.Navigate(UrltocompareList[index].Url2);
go = true;
}
steps++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
UrltocompareList is a collection of 2 sites to compare.
TotalSiteCount is the number of items in UrltocompareList.
The form for this inherit IOleClientSite to remove media such as images, videos and no active X download to have a faster rendering time in webbrowser control.
I use this method instead of system.net.webclient to get the html of a webpage then compare them.
I got this error when it hits the wb.Navigate method.
An issue I ran into when running specflow tests with watin in windows 10 is that win10 by default uses MS Edge, so I had never opened IE, and when watin started it IE was stuck on the prompt for using default settings. Selecting options, closing browser and running tests again worked for me.
Just something to watch
This can be solved pretty easily.
This error occurs when the browser commits an action while he's already performing an action.
For example, you are navigating to some website while you rightclick in the web browser.
To solve this, I did the follow:
//if my webbrowser isn't performing any actions
if(!myWebBrowser.IsBusy)
{
//Navigate
myWebBrowser.Navigate("http://www.google.com");
}
First Try
1- Please Check Navigate URL's (if you check, please check again compiled folder)
2- Delete WebBrowser Control and Add New
Me forget copy original file App.Path + "\error.html" and see this problem.
Guarantee Method
I Fix This Error in VB6
Add WebBrowserControl wb(0) (Name wb , Index=0)
And Before Ever Navigate
For i = 1 To wb.UBound
Unload wb(i)
Next
Load wb(1)
wb(0).Visible = False
wb(1).Visible = true
wb(1).Navigate URL

Categories