C# application is closed unexpectedly! - c#-4.0

I'm having a very frustrating problem. I have a c# win application. When I have clicked the button, the program closes itself after executed the click event handler. Even if I have debugged the code unfortunately I can't see any error, It just quits the program.
Where am I going wrong?
Here is the Code:
private void btnOpenFolder_Click(object sender, EventArgs e)
{
DialogResult dg = fd1.ShowDialog();
if (dg == DialogResult.OK)
{
lblInput.Text = fd1.SelectedPath;
btnOpenFolder.Enabled = false;
timerCallback = new TimerCallback(tmrQualityEvent);
tmrQuality = new System.Threading.Timer(timerCallback, null, 0, 1000);
Thread qualityThread = new Thread(new ThreadStart(QualityMapOpenFolder));
qualityThread.Start();
QualityMapOpenFolder();
}
}
void QualityMapOpenFolder()
{
fileList.Clear();
string path = lblInput.Text;
if (Directory.Exists(path))
{
foreach (var file in Directory.GetFiles(path))
{
if (Path.GetExtension(file) != ".kml")
{
fileList.Add(file);
}
}
SetProgressBarValue(0);
ChangeFileNameLabel(fileList[0]);
FileName = fileList[0];
}
else
SetText("Please make sure you have correctly set the open folder path!", true);
dataListQuality = GetInputData();
SetText("Calculated Data has been created, please click process files...", false);
SetProcessButtonStatus(true);
}

Attach an event handler to the UnhandledException handler and log it. Should help you to find out why your application is crashing.
Update: Now that you have posted some code:
You seem to update UI elements from another thread which you start. You should access UI components only from the thread on which they were created (usually the main thread). Consider using a BackgroundWorker
You start the QualityMapOpenFolder method on a thread and then you also call it after you started the thread - this seems a bit weird and has probably some unexpected side effects.

The common reason for this kind of behavior is unhandled exception in background thread. To prevent program.
#ChrisWue wrote on how to detect this kind of exceptions.
Also, often Windows Application log provides an insight on unhandled errors.
See here how to prevent killing app in this case.

Related

How can I update progress bar without blocking UI? [duplicate]

This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 1 year ago.
Currently I am creating a background STA thread to keep the UI responsive but it slows down my function calls on the main thread.
Based on this thread How to update progress bar while working in the UI thread I tried the following but the UI only gets updated after all of the work has finished. I tried playing around with the Dispatcher priorities but none of them seem to work.
What I also tried is adding _frmPrg.Refresh() to my Progress callback but this does not seem to change anything.
Dim oProgress = New Progress(Of PrgObject)(Sub(runNumber)
_frmPrg.Invoke((Sub()
_frmPrg.Status = runNumber
End Sub))
End Sub)
System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(Sub()
DoLongRunningWork(oProgress, _cancellationToken)
End Sub, System.Windows.Threading.DispatcherPriority.Background)
I can't really help you with your problem, but I'll try to clarify what happens in your posted code.
DoLongRunningWork will be invoked through Dispatcher on the UI thread, when the UI thread is not busy. But once started, it will block the UI thread until it completes. So you can't show a progress this way. Your single chance is, to let DoLongRunningWork run on a background thread. That brings you nothing, if the long-running methods come from office objects, which must be accessed from the UI thread...
The Progress class (see the remarks section) invokes your event handler on the UI thread automatically, so you don't need _frmPrg.Invoke in your event handler.
Maybe you can start a STAthread for your progress form and show it from there. The instance of your Progress class must be created in this thread too, but not before your form is shown to ensure, that the thread becomes a WindowsFormsSynchronisationContext (or you set one explicitly after starting the thread). A plain SynchronisationContext won't work!
At least you get updates in your form this way, but the UI thread of the office app will still be blocked. And of course, any action you make with your progress form must be invoked on the UI thread, if accessing office objects.
After reading some other posts, I decided to suggest another solution. My previous answer still contains usable information, so I'll leave it there. I'm not familiar with VB.NET syntax, so the samples are in C#. I have tested the code in a VSTO plugin for PowerPoint, but it should run in any office application.
Forget the Progress class and background threads. Run everything on the UI thread!
Now use some async code. To stay on the UI thread, we need a "good" SynchronizationContext.
private static void EnsureWinFormsSyncContext()
{
// Ensure that we have a "good" SynchronisationContext
// See https://stackoverflow.com/a/32866156/10318835
if (SynchronizationContext.Current is not WindowsFormsSynchronizationContext)
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
}
This is the event handler of a button. Note the manually added async keyword. The SynchronizationContext.Current gets resetted again and again, so ensure the good one in the EventHandler:
private async void OnButtonClick(object sender, EventArgs e)
{
EnsureWinFormsSyncContext();
// Return from event handler, ensure that we are really async
// See https://stackoverflow.com/a/22645114/10318835
await Task.Yield();
await RunLongOnUIThread();
}
This will be the worker method, also running on the UI thread.
private async Task RunLongOnUIThread()
{
//Dummy code, replace it with your code
var pres = addIn.Application.Presentations.Add();
for (int i = 0; i < 100; i++)
{
Debug.Print("Creating slide {0} on thread {1}", i, Thread.CurrentThread.ManagedThreadId);
// If you have some workloads that can be run on a background
// thread, execute them with await Task.Run(...).
try
{
var layout = pres.Designs[1].SlideMaster.CustomLayouts[1];
var slide = pres.Slides.AddSlide(i + 1, layout);
var shape = slide.Shapes.AddLabel(Microsoft.Office.Core.MsoTextOrientation.msoTextOrientationHorizontal, 0, 15 * i, 100, 15);
shape.TextFrame.TextRange.Text = $"Text on slide {i + 1}";
}
catch (Exception ex)
{
Debug.Print("I don't know what am I doing here, I'm not familiar with PowerPoint... {0}", ex);
}
// Update UI
statusLabel.Text = $"Slide {i + 1} done";
progressBar1.Value = i + 1;
// This is the magic! It gives the main thread the opportunity to update the UI.
// It also processes input messages so you need to disable unwanted buttons etc.
await IdleYield();
}
}
The following method is for Windows Forms Applications where it does the job perfect. I've tried it also in PowerPoint. If you are facing problems, try the WPF flavour with await Dispatcher.Yield(DispatcherPriority.ApplicationIdle) instead of await IdleYield().
private static Task IdleYield()
{
var idleTcs = new TaskCompletionSource<bool>();
void handler(object s, EventArgs e)
{
Application.Idle -= handler;
idleTcs.SetResult(true);
}
Application.Idle += handler;
return idleTcs.Task;
}
Here are the (clickable) links to the answers that I used (I can't put them in the code-blocks...).
Incorrect async/await working, Excel events in Excel Application Level Add-in
When would I use Task.Yield()?
Task.Yield - real usages?
If in your real code something runs not as expected, check the thread you are running on and SynchronizationContext.Current.

Add-in express and BackGroundWorker threading

Here's the problem:
I have an Outlook add-in made with add-in express.
It hosts a panel with the only winforms ElementHost, where WPF content is performing.
In this WPF control I have a textbox and button.
Button click triggers Backgroundworker to load info from database, in 'RunWorkerCompleted' process this data is being put into control.
When button is pressed - everything goes normally. But if I catch 'Enter' key press in textbox and then trigger BackgroundWorker - 'RunWorkerCompleted' is being launched not in the main thread, but in a thread pool, and cannot access WPF elements.
In both cases BackGroundWorker.RunWorkerAsync() is being called from Main thread, DoWork runs in thread pool, and only in case of enter-key-catch, RunWorkerCompleted also runs in a thread pool.
You've run into a bug in Add-in Express. In some cases Add-in Express event handlers are called with System.Threading.SynchronizationContext.Current set to null. BackgroundWorker use it in RunWorkerAsync method to save the ui context, so that is the problem.
To fix SynchronizationContext you could use the following workaround. Here MyAction is the method where you call RunWorkerAsync from.
var ctx = SynchronizationContext.Current;
if (ctx != null)
{
MyAction();
}
else
{
var timer = new DispatcherTimer();
timer.Tick += (s, a) =>
{
MyAction();
timer.Stop();
timer = null;
};
timer.Interval = TimeSpan.FromMilliseconds(10);
timer.Start();
}
Another solution would be saving the valid SynchronizationContext.Current value somewhere in a static member and then calling SynchronizationContext.Post in the event handler for the same purpose. I haven't tried this one though.

BlackBerry - App freezes when background thread executing

I have a BlackBerry App that sends data over a web service when a button has it state set to ON. When the button is ON a timer is started which is running continuously in the background at fixed intervals. The method for HttpConnection is called as follows:
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
return;
}
else
{
confirmation=PostMsgToServer(encryptedMsg);
}
The method PostMsgToServer is as follows:
public static String PostMsgToServer(String encryptedGpsMsg) {
//httpURL= "https://prerel.track24c4i.com/track24prerel/service/spi/post?access_id="+DeviceBoardPassword+"&IMEI="+IMEI+"&hex_data="+encryptedGpsMsg+"&device_type=3";
httpURL= "https://t24.track24c4i.com/track24c4i/service/spi/post?access_id="+DeviceBoardPassword+"&IMEI="+IMEI+"&hex_data="+encryptedGpsMsg+"&device_type=3";
//httpURL= "http://track24.unit1.overwatch/track24/service/spi/post?access_id="+DeviceBoardPassword+"&IMEI="+IMEI+"&hex_data="+encryptedGpsMsg+"&device_type=3";
try {
String C0NNECTION_EXTENSION = checkInternetConnection();
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
return null;
}
else
{
httpURL=httpURL+C0NNECTION_EXTENSION+";ConnectionTimeout=120000";
//Dialog.alert(httpURL);
HttpConnection httpConn;
httpConn = (HttpConnection) Connector.open(httpURL);
httpConn.setRequestMethod(HttpConnection.POST);
DataOutputStream _outStream = new DataOutputStream(httpConn.openDataOutputStream());
byte[] request_body = httpURL.getBytes();
for (int i = 0; i < request_body.length; i++) {
_outStream.writeByte(request_body[i]);
}
DataInputStream _inputStream = new DataInputStream(
httpConn.openInputStream());
StringBuffer _responseMessage = new StringBuffer();
int ch;
while ((ch = _inputStream.read()) != -1) {
_responseMessage.append((char) ch);
}
String res = (_responseMessage.toString());
responce = res.trim();
httpConn.close();
}
}catch (Exception e) {
//Dialog.alert("Connection Time out");
}
return responce;
}
My Question: The App freezes whenever the method is called, i.e. whenever the timer has to execute and send data to the web service the App freezes - at times for a few seconds and at times for a considerable amount of time applying to the user as if the handset has hanged. Can this be solved? Kindly help!!
You are running your networking operation on the Event Thread - i.e. the same Thread that processes your application's Ui interactions. Networking is a blocking operation so effectively this is stopping your UI operation. Doing this on the Event Thread is not recommended and to be honest, I'm surprised it is not causing your application to be terminated, as this is often what the OS will do, if it thinks the application has blocked the Event Thread.
The way to solve this is start your network processing using a separate Thread. This is generally the easy part, the difficult part is
blocking the User from doing anything else while waiting for the
response (assuming you need to do this)
updating the User Interface with the results of your networking
processing
I think the second of these issues are discussed in this Thread:
adding-field-from-a-nonui-thread-throws-exception-in-blackberry
Since it appears you are trying to do this update at regular intervals in the background, I don't think the first is an issue, - for completeness, you can search SO for answers including this one:
blackberry-please-wait-screen-with-time-out
There is more information regarding the Event Thread here:
Event Thread

How to use the Asynchronous Command in UI built using LWUIT ResourceEditor

I am using LWUIT ResrouceEditor(latest SVN code revision 1513) to generate a UI State machine.
I want to show a wait screen when a long running command is invoked by a user using a button on the current form. I believe I can use the asynchronous option when linking the command on the button. I have setup a form in which I have a button which should invoke the asynchronous command. In command selection for that button, I have set the action to show the wait screen form and have marked the command as asynchronous. However when I use the asynchronous option, the code shows the wait screen, but after that it throws a NullPointerException.
As per my understanding, once you mark a command as asynchronous, it will call the following methods from a different thread where you can handle its processing.
protected void asyncCommandProcess(Command cmd, ActionEvent sourceEvent);
protected void postAsyncCommand(Command cmd, ActionEvent sourceEvent);
However this methods are not getting called and it throws a NullPointerException.
When I looked at the LWUIT code, in UIBuilder.java(lineno. 2278), I see that it constructs the new thread for an asynchronous command as follows:
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
But when running it through Debugger I see that currentAction and currentActionEvent are always null. And hence when the FormListener thread starts running, it never calls the above two async command processing methods. Please see the listing of the run() method in the UIBuilder.java(line no. 2178)
public void run() {
if(currentAction != null) {
if(Display.getInstance().isEdt()) {
postAsyncCommand(currentAction, currentActionEvent);
} else {
asyncCommandProcess(currentAction, currentActionEvent);
// wait for the destination form to appear before moving back into the LWUIT thread
waitForForm(destForm);
}
} else {
if(Display.getInstance().isEdt()) {
if(Display.getInstance().getCurrent() != null) {
exitForm(Display.getInstance().getCurrent());
}
Form f = (Form)createContainer(fetchResourceFile(), nextForm);
beforeShow(f);
f.show();
postShow(f);
} else {
if(processBackground(destForm)) {
waitForForm(destForm);
}
}
}
}
In the above method, since the currentAction is null, it always goes into the else statement and since the nextForm is also null, it causes the NullPointerException.
On further look at the UIBuilder.java code, I noticed what is causing the NullPointer exception. It seems when the FormListner is created, it is passed currentAction and currentActionEvent, however they are null at that time. Instead the code should be changed as follows(starting at line 2264):
if(action.startsWith("#")) {
action = action.substring(1);
Form currentForm = Display.getInstance().getCurrent();
if(currentForm != null) {
exitForm(currentForm);
}
Form f = (Form)createContainer(fetchResourceFile(), action);
beforeShow(f);
/* Replace following with next lines for fixing asynchronous command
if(Display.getInstance().getCurrent().getBackCommand() == cmd) {
f.showBack();
} else {
f.show();
}
postShow(f);
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
*/
new Thread(new FormListener(cmd, evt, f)).start();
return;
}
Can lwuit development team take a look at the above code, review and fix it. After I made the above change, the asynchronous command processing methods were invoked.
Thank you.
Thanks for the information, its probably better to use the issue tracker for things like this (at http://lwuit.java.net).
I will make a similar change although I don't understand why you commented out the form navigation portion.
To solve your use case of a wait screen we have a much simpler solution: Next Form. Just show the wait screen and in it define the "Next Form" property.
This will trigger a background thread to be invoked (processBackground callback) and only when the background thread completes the next form will be shown.

Windows Phone 7 Audio Recording Problem

I'm hoping someone can help me with this. I have found the examples for recording audio using XNA in a Silverlight application. And it works, however, only the first time in. I have all the recording functionality on a seperate WP7 Page and with successive visits to the page it doesn't work. The best I can tell is the microphone.start is getting called but the micophone.status remains stopped. What is weird is the BufferReady keeps getting called and the code within that function is all running but without the microphone really starting nothing is really happening. When you exit the app and come back in again the first time visit to the page and everything works fine, but a revisit to the page and it doesn't.
void microphone_BufferReady(object sender, EventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
microphone.GetData(buffer);
stream.Write(buffer, 0, buffer.Length);
TimeSpan tsTemp = timer.Elapsed;
TextBlockSeconds.Text = tsTemp.Hours.ToString().PadLeft(2, '0') + ":" + tsTemp.Minutes.ToString().PadLeft(2, '0') + ":" + tsTemp.Seconds.ToString().PadLeft(2, '0');
if(timer.Elapsed.Seconds >5)
DoStop();
});
}
private void ButtonRecord_Click(object sender, RoutedEventArgs e)
{
DisableRecordButton();
timer = new Stopwatch();
timer.Start();
stream = new MemoryStream();
TextBlockSeconds.Text = "00:00:00";
TextBlockStatus.Text = "Recording: ";
microphone.BufferDuration = TimeSpan.FromMilliseconds(500);
buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];
microphone.BufferReady += new EventHandler<EventArgs>(microphone_BufferReady);
microphone.Start();
}
private void DoStop()
{
if (timer.IsRunning)
timer.Stop();
if (microphone.State == MicrophoneState.Started)
{
microphone.Stop();
TextBlockStatus.Text = "Stopped: Ready to save";
}
else
{
TextBlockStatus.Text = "Ready: ";
}
TextBlockSeconds.Text = string.Empty;
EnableRecordButton();
}
Update...
I found the problem but no solution. I was calling the microphone.stop via code on a timer (so I could limit the recorded audio to 5 seconds). Exact same code to execute when a manual stop button would be clicked. When clicking the manual stop button everything worked fine, could re-visit the page and all would be fine. When the stop was called in code from the timer, next visit to the page would not work. So I implemented it with only a manual stop button but really would have been nice to do it automatically (and to know what the real issue was).
actually when you are navigating away from the page you can add
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
this.MicroPhone.BufferReady -= this.Microphone_BufferReady;
}
and when you are returning to page add
this.MicroPhone.BufferReady += this.Microphone_BufferReady;
You can add this statement either in a page loaded event or an OnNavigatedTo event
Added string name = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() to make sure that it was on the same thread (and it was).
But finally worked this out, the problem is the microphone.stop doesn't stop the microphone from continuing to fire the buffer ready event (like I was expecting). And it would seem the way the page is cached this causes some weird problems with that event still firing. So I added the code
microphone.BufferReady -= new EventHandler<EventArgs>(microphone_BufferReady);
to my code for stopping, and it all works now.
I can't see from your code how you're stopping the timer/microphone if you navigate away from the page and don't manually stop it.
If that's not it, are you ensuring that all your microphone operations are being executed on the same thread? (Just a thought.)

Resources