I have a fairly complex c# application that runs on Windows Mobile 5.0 and later. It includes code that uses SQL CE, updates GPS coordinatess on a seperate thread, and also uses Microsoft Sync Framework in a seperate thread to sync to a server in the background. The application generally runs fairly well, but every so often out in production, the application main window disappears.
I have a code like to the following in the Program.cs file:
static class Program
{
private static NLog.Logger _logger = NLog.LogManager.GetLogger("Program");
[MTAThread]
static void Main()
{
try
{
_logger.Info("Program V {0} starting.", Utility.AppVersion);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new MainForm());
_logger.Info("After Application.Run().");
}
catch (Exception ex)
{
_logger.ErrorException("Exception occurred.", ex);
}
}
static void MobileDevice_Hibernate(object sender, EventArgs e)
{
_logger.Info("Hibernate was received.");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_logger.ErrorException("Unhandled exception was thrown", e.ExceptionObject as Exception);
}
}
I see the starting info log as expected, and when the application disappears, I also get the After Application.Run() message. But I do not get the messages logged in the MainForm.Closing event, so it seems that it is never called. I also do not get any exception logged from either the exception handler around the Application.Run or the UnhandledException handler. I thought it might be related to running low/out of memory and that is why I have the Hibernate event wired up as well. But I do not get the Hibernate event either.
Any help, or suggestions would be appreciated as I am out of ideas and things to check.
Well, at the risk of stating the obvious, something is crashing your app that is preventing your Closing Event from firing.
For your items that run on separate threads (most likely suspects), can you create class containers for them that implement IDisposable? Then, you could place NLog references in your Dispose() methods to record your data.
public class FirstClass : IDisposable {
private bool isDisposed;
public FirstClass() {
isDisposed = false;
}
public void Dispose() {
_logger.Info("FirstClass is done.");
isDisposed = true;
}
public void Method1() {
while (!isDisposed) {
// your code here
}
}
}
You would need to create a way so that _logger can be accessible to this class, however.
Bugs in threads can be hard to catch.
Related
Let's say a windows service crashes, and automatically restarted due to some recovery options. I want to run some code in the program (C#) that will do some network action (send an alert that it shut down) whenever this happens.
Is there an event I can apply or code I can have run after that occurs?
Thanks!
In this situation what I would do is instead of having something that gets written out when the program fails, have the program write out some kind of record to persistent storage that it then deletes if it detects a clean shutdown is being done.
public partial class MyAppService : ServiceBase
{
protected override void OnStart(string[] args)
{
if(File.Exists(Path.Combine(Path.GetTempPath(), "MyAppIsRunning.doNotDelete"))
{
DoSomthingBecauseWeHadABadShutdown();
}
File.WriteAllText(Path.Combine(Path.GetTempPath(), "MyAppIsRunning.doNotDelete"), "");
RunRestOfCode();
}
protected override void OnStop()
{
File.Delete(Path.Combine(Path.GetTempPath(), "MyAppIsRunning.doNotDelete"));
}
//...
}
This could easily have the file swapped out with a registry entry or a record in a database.
You can subscribe to below event which will fire no matter in which thread the exception occurs..
AppDomain.CurrentDomain.UnhandledException
Sample implementation
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// log the exception ...
}
In the windows 8.1 universal apps, the suspend/resume modes were handled using the NavigationHelper.cs ans SuspensionManager.cs classes included in the APP template. These classes doesn't seem to be there in the windows 10 UWP apps. Is there a way by which we can handle the suspend/resume states?
There's an interesting framework being developed by the community (but mostly I think Jerry Nixon, Andy Wigley etc.) called Template10. Template10 has a Bootstrapper class with OnSuspending and OnResuming virtual methods that you can override. I am not sure that there's an exact example of doing suspension/resuming yet with Template10, but the idea seems to be to make App.xaml.cs inherit from this Bootstrapper class so you can easily override the methods I mentioned.
sealed partial class App : Common.BootStrapper
{
public App()
{
InitializeComponent();
this.SplashFactory = (e) => null;
}
public override Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
// start the user experience
NavigationService.Navigate(typeof(Views.MainPage), "123");
return Task.FromResult<object>(null);
}
public override Task OnSuspendingAsync(object s, SuspendingEventArgs e)
{
// handle suspending
}
public override void OnResuming(object s, object e)
{
// handle resuming
}
}
The above solution will only work for people who install Template10.
The generic solution is,
paste these lines in the constructor of App.xaml.cs
this.LeavingBackground += App_LeavingBackground;
this.Resuming += App_Resuming;
It will look like this
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.LeavingBackground += App_LeavingBackground;
this.Resuming += App_Resuming;
}
These are the methods, although you can press TAB and they will autogenerate.
private void App_LeavingBackground(object sender, LeavingBackgroundEventArgs e)
{
}
private void App_Resuming(object sender, object e)
{
}
The methods LeavingBackground and the one not mentioned here EnteredBackground are newly added to uwp.
Before these methods we would use resuming and suspending to save and restore ui, but now the recommended place to do that work is here.Also these are the last places to perform work before the app is resumed. So the work on these methods should be small ui or other stuff like remaking values which are stale as a long held method here will affect app startup time while resuming.
Source
Windows dev material ,
Windoes dev material 2
Thanks , and have a good day.
My DAL doesn't handle exceptions and it will be propagated up to the calling method in the presenter classes where the exception will be handled.
I'm using a single handler called ExecutAction(Action action) so I'm catching exceptions in one place rather than repeating in every method.
At the moment, I'm not logging errors. Just alert the user for an action and try to keep the system alive if possible.
When showing messages to users, Presenters will use a static class called MessagingService. (ShowErrorMessage()). So that I can customize all massage boxes in one place.
private void Search()
{
ExecutAction(() =>
{
var info = _DataService.GetByACNo(_model.AccountNumber);
if (info != null)
{
_Model = info ;
this.SetViewPropertiesFromModel(_Model, _View);
}
else
{
MessageBox.Show ("Bank account not found");
}
});
}
private void ExecutAction(Action action)
{
try
{
action();
}
catch (NullReferenceException e) { MessagingService.ShowErrorMessage(e.Message); }
catch (System.Data.SqlTypes.SqlTypeException e) { MessagingService.ShowErrorMessage(e.Message); }
catch (System.Data.SqlClient.SqlException e) { MessagingService.ShowErrorMessage(e.Message); }
}
}
Should I include general exception handler to this, to be able to handle any unforeseen exceptions?
Also could you show me a better way to handle showing messages than using a static?
Does use of lambda statements in every method call (ExecutAction(() =>) degrade code readability?
When showing user messages how to show a custom message like "Check the server connection" etc. first and then if the user wants more information (like StackTrace / technical details) he /she could press a button like More Info which is in the MessageBox dialog?
I agree with jeffrey about trying to incorporate IoC for your message service. You could define an abstract base presenter class that has a dependency on an interface for your message service. The base class would be responsible for handling the delegate execution + exception logging.
public interface IMessageService
{
void ShowErrorMessage(Exception e);
}
public abstract class PresenterBase
{
private readonly IMessageService _messageService;
public PresenterBase(IMessageService messageService)
{
this._messageService = messageService;
}
protected void ExecuteAction(Action action)
{
try
{
action();
}
catch (Exception e) { this._messageService.ShowErrorMessage(e); }
}
}
public class SearchPresenter: PresenterBase
{
public SearchPresenter(IMessageService messageService)
: base(messageService)
{
}
public void Search()
{
this.ExecuteAction(() =>
{
//perform search action
});
}
}
Regarding your question about catching all exeptions. Unless you are doing something special for specific types of exceptions, I would suggest just handling all the same. The example I provided passes the exception to the message service so that the formatting specifics can be handled by your message service.
If you have not yet incorporated any sort of IoC container, you can always start by using the interface injection and then passing the instance explicitly from the child class constructor.
public class SearchPresenter: PresenterBase
{
public SearchPresenter()
: base(new SomeMessageService())
{
}
...
}
This is at least removes the static dependency and is not too dificult to swap out later if you ever introduce an IoC container.
I think your approach is good enough for your work. Wrapping logics by ExecuteAction is an acceptable way to me. As another option, I might use AOP for centralized exception handling in practice.
Also, I might use a MessagingService resolved from dependency injection container rather than a static one.
Regarding how to display the error, that's totally depend on your business purpose. For example, you could simply log the error and tell the user "something's wrong", or show them the complete stacktrace including the environment information so they could simply copy & paste in the email.
I have the following code:
public class BaseControlClass : System.Web.UI.UserControl
{
protected delegate void AsyncronousAction();
protected virtual void FAsyncEvent() { } //Overidden on derived classes.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
FPerformAsyncronousTasks(FAsyncEvent);
}
protected virtual void FPerformAsyncronousTasks(AsyncronousAction AsyncCallback)
{
new Thread(delegate()
{
AsyncCallback();
}).Start();
}
}
public class DerivedControlClass : BaseClass
{
protected override void FAsyncEvent()
{
//Contact web service, wait for results, add to local database.
}
}
What I was expecting is for the page to load and the code in FAsyncEvent() in my derived class to run behind the scenes however, the page doesn't finish loading until the code in FAsyncEvent() has completed.
Am I doing something wrong with the threading here?
EDIT Strangely, I have noticed if I do a Clean -> Build then run the code, it works fine and the page finishes loading whilst the web service is being contacted. Subsequent runs though mean the page waits until the thread has finished processing.
Your code keeps the reference to the UserControl alive, which might be preventing the request from continuing. Try passing a static method to the new thread, just as a quick check and see if it helps.
I'm creating a wpf application which performs many tasks in the backgound, but still requires the UI to be responsive and to display the status of the various background tasks. It also has the option to not display the UI at all, in which case the status messages should be discarded without creating an instance of the main form at all.
What I've attempted is to remove
StartupUri="MainWindow.xaml"
from App.xaml. Then, in App.xaml.cs, I have
`
public App()
{
Startup += new StartupEventHandler(App_Startup);
}
void App_Startup(object sender, StartupEventArgs e)
{
// Code which loads application settings is here
if (pf.ShowUI)
{
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
}
// The background processes will begin here.
}`
This shows the main form, if necessary, and starts all the background processes. This part works.
In order to send messages from the background to the UI, I've implemented a very basic messenger:
`
internal interface IMessageHandler
{
void ReceiveMessage(string message);
}
internal class Messenger
{
private static List<IMessageHandler> _handlers;
internal static void AddHandler(IMessageHandler handler)
{
_handlers.Add(handler);
}
internal static void RemoveHandler(IMessageHandler handler)
{
try
{
_handlers.Remove(handler);
}
catch (Exception ex) {}
}
internal static void Broadcast (string message)
{
foreach (IMessageHandler handler in _handlers)
{
handler.ReceiveMessage(message);
}
}
}`
The main form implements the IMessageHandler interface, and adds itself to the Messenger as a handler when it starts up. Any process that needs to send a status to the main form just needs to call the Broadcast method of the messenger.
The problem I'm having, is that the messages are not being shown on the form until the background processes complete, and the UI is locked up until then as well.
The code in the UI which handles receiving messages is as follows:
`
public void ReceiveMessage(string message)
{
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
}
private void AddText(string text)
{
Label myLabel = new Label();
myLabel.Content = text;
stackPanel1.Children.Add(myLabel);
if (stackPanel1.Children.Count > 5)
{
stackPanel1.Children.RemoveAt(0);
}
}`
Why are my background processes freezing my UI? What can I do to prevent it? And why is my UI not updating with the status messages?
Maybe this is your problem:
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
Try change this to,
Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
Because when you use Invoke, the method gets executed and the application waits for it to complete, but with BeginInvoke the method is invoked Asychnronously and the application continues to execute while the method referenced in BeginInvoke is executed.
Read this: whether to use Invoke or BeginInvoke
Use the below code to avoid freezing the UI. In my application I have used a BackgroundWorker class. By changing anything on the form using code, a run time error is thrown.
I am using the below code to avoid this and it works perfectly for me.
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
rtf_status.AppendText("Validating XML against schema...Please wait\n");
}));
Note the part after the between braces ('{}') this is where you should place your code if you wish to change something on the form.