I can't close my WPF application because the NamedPipeClientStream endlessly runs. I tried using ConnectAsync, I tried disposing it, but no matter what it prevents the process from ending.
I use the pipe to listen for messages so it needs to run until the application quits.
This is my current attempt:
public MainWindow()
{
namedPipeClient = new(System.Configuration.ConfigurationManager.AppSettings["AppGUID"]!);
Thread PipeThread = new(() =>
{
while (true)
{
try
{
PipeReceive();
}
catch (TimeoutException) { }
catch (ObjectDisposedException) { break; }
}
});
PipeThread.Start();
}
// Called when window is closed
protected override void OnClosed(EventArgs e)
{
namedPipeClient.Close();
namedPipeClient.Dispose();
base.OnClosed(e);
}
private void PipeReceive()
{
namedPipeClient.Connect(1000);
if (namedPipeClient.IsConnected)
{
// Retrieve message
}
}
The issue didn't have anything to do with named pipes. I was under the impression it did because in Visual Studio's "Running Tasks" it showed a reference to the named pipe methods and listed them as active.
The real issue was the I had changed the application ShutdownMode to OnExplicitShutdown so even after the main window was closed the application would remain running unless the Shutdown() method is called. My fix was to override the OnClosed event.
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
System.Windows.Application.Current.Shutdown();
}
Related
I created a windows service project with Visual Studio. This service should run in the background and poll data every X seconds. The polling is achieved with a timer and a tick event. So whenever the tick event is raised the service should do something.
Unfortunately the service closes itself because it does not wait for the timer to tick. The OnStart method gets executed and runs but after that the service closes itself.
I added a debug mode to my program file
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
#else
ServiceBase.Run(new RuntimeService());
#endif
}
and use this code for my service application
public partial class RuntimeService : ServiceBase
{
private const int BATCH_POLLING_INTERVAL = 3000;
private Timer batchPollingTimer;
public RuntimeService()
{
InitializeComponent();
}
public void RunDebugMode()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
try
{
// ...
batchPollingTimer = new Timer(BATCH_POLLING_INTERVAL);
batchPollingTimer.Elapsed += OnTimer;
batchPollingTimer.Enabled = true;
}
catch (Exception exception)
{
throw exception;
}
}
protected override void OnStop()
{
batchPollingTimer.Enabled = false;
try
{
// ...
}
catch (Exception exception)
{
throw exception;
}
}
private void OnTimer(object sender, ElapsedEventArgs e)
{
batchPollingTimer.Enabled = false;
// ...
batchPollingTimer.Enabled = true;
}
}
How can I run the service without closing it and waiting for the timer ticks? By "closing itself" I mean executing the Main method and ignoring the timer. Please let me know if you need more information.
It will only do this in debug mode, because there is nothing stopping it from ending. Ordinarily ServiceBase.Run will not return unless the service is shutting down. Add a sleep for a long time so that after your main thread has kicked off your timer, it will go to sleep rather than exiting the Main
Something like:
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
System.Threading.Thread.Sleep(TimeSpan.FromDays(1));
#else
ServiceBase.Run(new RuntimeService());
#endif
}
As an aside, consider putting your timer stop/start in a try/finally - at the moment if something happens in your OnTimer, your stopped timer will never restart and your service will cease doing anything (but may not crash entirely)
private void OnTimer(object sender, ElapsedEventArgs e)
{
try{
batchPollingTimer.Enabled = false;
// ...
} finally {
batchPollingTimer.Enabled = true;
}
}
}
My head started to spin: I have a windows phone 8.1 universal app. In App.xaml.cs I have implemented the following methods:
public sealed partial class App : Application
{
public static bool isSuspended = false;
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
this.Resuming += this.OnResuming;
}
private void OnSuspending(object sender, SuspendingEventArgs e)
{
SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral();
App.isSuspended = true;
// TODO: Save application state and stop any background activity
deferral.Complete();
}
private async void OnResuming(object sender, object e)
{
App.isSuspended = false;
}
}
In my MainPageVM (it is a View Model) I have implemented the following methods:
private async void onPushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)
{
switch (args.NotificationType)
{
case PushNotificationType.Toast:
if (App.isSuspended)
{
args.ToastNotification.Activated += this.toastNotification_Activated;
}
else
{
args.Cancel = true;
this.manageNotification(args.ToastNotification.Content)
}
break;
case PushNotificationType.Raw:
break;
}
}
private void toastNotification_Activated(ToastNotification sender, object args)
{
ToastActivatedEventArgs tArgs = (ToastActivatedEventArgs)args;
this.manageNotification(tArgs.Arguments);
}
It runs well when the app is killed or when the app is in foreground. The problem comes when the app is in background: when user clicks the notification, toastNotification_Activated never gets raised.
What am I missing?
When your app is Suspended it means that it's not running (app lifecycle at MSDN). In this case when the notification comes it's not intercepted by the event you have declared, like MSDN says:
Note This procedure applies only to running apps. Notifications that the system sends when the app is not running and the handler is not implemented are delivered normally—tiles are updated, toast is shown, and raw notifications are delivered to background tasks (if implemented).
If you want to handle the notification in the background, then you may think of declaring a Background Task for it.
I have a c++/cli wrapper class which grabs frames from a camera and sends them as events.
A WPF test application Starts the camera, and updates the images.
When I click Stop, it usually ends in a deadlock, on m->streamThread->Join(). I'm suspecting the problem has to do with the frame handling event in the WPF, rather than the wrapper code.
namespace WpfTestApp
{
public partial class Window1 : Window
{
private void OnFrameArrived(object sender, EventArgs e)
{
Action a = delegate
{
// this uses Imaging.CreateBitmapSourceFromMemorySection
// to copy the frame data to the image memory
m_colorImage.UpdateImage(e.Image);
};
Dispatcher.Invoke(a);
}
private void startBtn_Click(object sender, RoutedEventArgs e)
{
m_camera.FrameArrived += m_frameHandler;
m_camera.Start();
}
private void Stop()
{
m_camera.FrameArrived -= m_frameHandler;
m_camera.Stop();
}
}
}
// Camera.h
public ref class Camera
{
public:
delegate void FrameArrivedHandler(Object^ sender, DGEventArgs^ e);
event FrameArrivedHandler^ FrameArrived;
void Start();
void Stop();
private:
void StreamThreadWorker();
Thread^ m_streamThread;
bool m_isStreaming;
}
// Camera.cpp
void Camera::Start()
{
if (m_isStreaming)
return;
m_isStreaming = true;
m_streamThread = gcnew Thread(gcnew ThreadStart(this, &Camera::StreamThreadWorker));
m_streamThread->Start();
}
void Camera::Stop()
{
if (!m_isStreaming)
return;
m_isStreaming = false;
m_streamThread->Join(); // stuck here
}
void Camera::StreamThreadWorker()
{
EventArgs^ eventArgs = gcnew EventArgs();
while (m_isStreaming)
{
eventArgs->Image = Camera->GetImage();
FrameArrived(this, eventArgs);
}
}
likely what happens is: you click Stop, this gets handled in the WPF ui dispatcher thread. So the Join call is in the ui dispatcher thread. However this same thread is also responsible for drawing the frames (the invoked call to UpdateImage). As a result, the StreamThreadWorker is waiting on FrameArrived to finish, but that cannot finish because the thread is waiting for Stop to finish. There's your deadlock.
So in order to get the StreamThreadWorker to finish, it must not be blocked by Stop. An easy way to achive this is to stop the thread from within another thread:
void Camera::Stop()
{
...
gcnew Thread( gcnew ThreadStart( this, &Camera::DoStopThread ) )->Start();
}
void Camera::DoStopThread()
{
if( !m_streamThread.Join( 3000 ) )
HandleThreadDidNotStopInTimeError(); //notify listeners there's a serious problem
m_streamThread.Abort();
m_streamThread = null;
RaiseThreadStoppedEvent(); //notify listeners that the thread stopped
}
I am using a Prism UnityExtensions bootstrapper class to start my WPF application. How do I shutdown the application while the unityextensions bootstrapper is still running?
See my bootstrapper class below. The SomeClass object may throw a custom exception (fatal). If the custom exception is thrown, I need to close the application. I am using Application.Current.Shutdown() to shutdown the application.
However, the bootstrapper code continues running, and I get a "ResolutionFailedException was unhandled" exception error when setting the datacontext in the CreateShell() method. Obviously, the SomeClass method and interface were not registered with the container due to the catch block.
It appears that the bootstrapper code continues running after a call to Application.Current.Shutdown() was called. I need to stop the bootstrapper code immediately following the call to shutdown.
Any ideas how to shutdown the application without creating the ResolutionFailedException?
ResolutionFailedException exception details -->
Resolution of the dependency failed, type = "SomeClass", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, SomeClass, is an interface and cannot be constructed. Are you missing a type mapping?
public class AgentBootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
var eventRepository = new EventRepository();
Container.RegisterInstance(typeof(IEventRepository), eventRepository);
var dialog = new DialogService();
Container.RegisterInstance(typeof(IDialogService), dialog);
try
{
var someClass = new SomeClass();
Container.RegisterInstance(typeof(ISomeClass), SomeClass);
}
catch (ConfigurationErrorsException e)
{
dialog.ShowException(e.Message + " Application shutting down.");
**Application.Current.Shutdown();**
}
}
protected override System.Windows.DependencyObject CreateShell()
{
var main = new MainWindow
{
DataContext = new MainWindowViewModel(Container.Resolve<IEventRepository>(),
Container.Resolve<IDialogService>(),
Container.Resolve<ISomeClass>())
};
return main;
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)Shell;
Application.Current.MainWindow.Show();
}
}
This behaviour occurs, because you´re executing the OnStartup of your Application at this time. I suppose you do it like that:
protected override void OnStartup(StartupEventArgs e)
{
new AgentBootstrapper().Run();
}
The OnStartup has to be completed, before the App can shutdown, so the bootstrapper continues execution. You might throw another exception to get out of the Run():
... catch (ConfigurationErrorsException e)
{
dialog.ShowException(e.Message + " Application shutting down.");
throw new ApplicationException("shutdown");
}
And then catch it in the StartUp():
protected override void OnStartup(StartupEventArgs e)
{
try
{
new AgentBootstrapper().Run();
}
catch(ApplicationException)
{
this.Shutdown();
}
}
I have the following classes:
using System;
using System.Windows.Forms;
namespace FastEyeControl
{
public partial class ConnectView : Form, IConnectView
{
private IConnectPresenter m_Presenter;
public ConnectView()
{
InitializeComponent();
m_Presenter = new ConnectPresenter(this);
}
public string Hostname
{
get
{
return m_Hostname.Text;
}
}
public int Port
{
get
{
return Convert.ToInt32(m_Port.Text);
}
}
public void ShowMessage(string message)
{
MessageBox.Show(message,
"Success",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
public void ShowError(string message)
{
MessageBox.Show(message,
"ERROR!",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
private void m_ConnectButton_Click(object sender, EventArgs e)
{
m_Presenter.ConnectButtonPressed();
}
}
}
The presenter class:
using System;
using System.Collections.Generic;
namespace FastEyeControl
{
public class ConnectPresenter : IConnectPresenter
{
private IConnectView m_View;
private IConnectModel m_Model;
public ConnectPresenter(IConnectView view)
{
m_View = view;
m_Model = FastEyeClient.Instance;
}
public void ConnectButtonPressed()
{
m_Model.Connect(m_View.Hostname, m_View.Port);
}
private void ConnectionComplete(object sender, ConnectionEventArgs e)
{
// Code here indicating whether connection was successful and informing the view.
// i.e...
if (e.IsConnected)
{
m_View.ShowMessage("Successfully connected.");
}
else
{
m_View.ShowError("Unable to connect.");
}
}
}
}
The model code runs in another thread. The problem is that when I call m_Model.Connect(), I'm calling code that's usually running in another thread within the main thread still (the UI thread). This is not a database connection. This is a TCP/IP connection to a server. If I set a variable within the model, then I am doing this from the UI thread which is not thread safe.
I know that with user controls, they have InvokeRequired and Invoke/BeginInvoke operations that will handle this situation. But that is for user controls only. I know you can't just interrupt another thread in the middle of its execution and tell it to call another method instead. I basically want the non-UI thread to call the Connect code somehow.
Just as a test, I tried using a delegate (fire off an event whenever I want to connect) and when I look in the debugger, the Connect code is still running in the UI thread.
I need a multi-threaded event queue essentially. What's the best way to achieve what I want to do here? Thanks!
public void ConnectButtonPressed()
{
var threadedTask = () => m_Model.Connect(m_View.Hostname, m_View.Port);
threadedTask.BeginInvoke(null,null);
}
This will, no question, use a background thread from the ThreadPool to do the work. Maybe you had tried to call the delegate directly, or called Invoke() on it; that will execute the delegate synchronously.
Now, BeginInvoke is simple to set up, but it has its limitations; you cannot cancel execution of the background thread, and if it throws an exception you cannot catch it in the invoking thread.
You can use BackgroundWorker.