C# Shutdown A Thread That Uses Application.Run() - c#

I'm trying to use a C# DLL that I have access to the code of, but I can't actually change the code and build a custom version of it. The calling code is a C# WinForms project and the C# DLL also uses WinForms to handle Windows system events. The problem is that the DLL uses Application.Run() inside of it using a background thread, and there's built-in way to kill or stop that thread. Here is a snippet of the code:
public class DllClass
{
private Thread uithread = null;
private bool uithreadstarted = false;
public DllClass()
{
uithread = new Thread(new ThreadStart(RunDll));
uithread.IsBackground = true;
uithread.SetApartmentState(ApartmentState.STA);
uithread.Start();
do
{
Thread.Sleep(100);
} while (uithreadstarted == false);
}
private void RunDll()
{
//other init stuff here
uithreadstarted = true;
Application.Run();
}
}
Apparently the way I'm expected to kill it is by using Application.Exit(), but that also exits my own WinForms project, which is not what I want to happen. If I just close my application without calling Application.Exit(), the DLL continues running in the background. I want to be able to instantiate the DllClass object, use it, and then shut it down when I'm done. I came up with a method to get the Thread object of the thread that it's running in, but calling Thread.Abort() on it does not actually kill the thread. Is there any way to forcibly abort the Application.Run() call from outside of the DLL?

If you can find a window handle that was created by the DLL background thread (such as a form or hidden application window), you can post a WM_QUIT message to that handle and that should cause the DLL to exit the message loop cleanly.

you will need to get an instance of the form that is running in the other thread then call form.BeginInvoke and from there call Application.Exit

How about Application.ExitThread

Related

Console Application with Message Pump

I'm trying to write a console application (C# .NET) that makes use of un-managed code in a 3rd party DLL.
The external assembly makes extensive use of callbacks. The sample application I have uses Windows Forms.
The sample code (Windows Forms) makes use of ThreadPool.QueueUserWorkItem
ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectToControlPanel));
It would seem that with windows forms there is a message pump that handles the callbacks. This is not the case with a console app so I need to construct my own.
I've tried adding a reset event
private static ManualResetEvent resetEvent = new ManualResetEvent(false);
static void main()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectToControlPanel));
resetEvent.WaitOne();
}
private void ConnectToControlPanel()
{
//Call external function from unmanaged DLL
resetEvent.Set();
}
That doesn't work.
My problem seems to be very much like this one but there is no real solution other than using Win.Forms and calling Application.DoEvents()
Edit
I modified my code thus:
Task task = Task.Factory.StartNew(() => ConnectToControlPanel());
while (task.Status != TaskStatus.RanToCompletion)
{
Application.DoEvents();
Thread.Sleep(500);
}
This works, the callbacks get called on progress and the result is successful rather than a timeout.
It doesn't feel right though to have to run that ugly loop every time I make an external call.
I've also tried spinning up another thread that constantly calls Application.DoEvents() but that didn't work, so I'm assuming it's got something to do with running in the same thread that made the call.

Releasing a named mutex created in WPF Application.OnStartUp(): Which thread owns it?

I create a mutex within the OnStartup Method of a WPF app. The mutex is not used anywhere else in the program, its only purpose is to prevent certain programs from running concurrently. How can I release this mutex when the application closes?
According to the documentation, mutex.ReleaseMutex() must be called from the same thread that created the mutex. However this presents a problem, since I do not control the thread that calls OnStartup().
Suppose my OnStartup method looks like this:
public partial class App : Application
{
private Mutex mutex;
private bool hasHandle = false;
protected override void OnStartup(StartupEventArgs e)
{
bool createdNew;
mutex = new Mutex(false, #"Global\XYZ", out createdNew);
try
{
hasHandle = mutex.WaitOne(5000, false);
if (!hasHandle)
{/*do stuff*/};
}
catch (AbandonedMutexException)
{
hasHandle = true;
// do stuff
}
base.OnStartup(e);
}
private void releaseMutex()
{
if (mutex!=null)
{
if (hasHandle) mutex.ReleaseMutex();
mutex.Dispose();
}
}
}
Is it save to call releaseMutex() ...
in the OnExit() method?
protected override void OnExit(){releaseMutex();}
in the ProcessExit event handler?
AppDomain.CurrentDomain.ProcessExit += (sender,e)=> releaseMutex();
in a finalizer?
~App(){releaseMutex();}
in the unhandled exception event handler?
AppDomain.CurrentDomain.UnhandledException += (sender,e)=> releaseMutex();
It seems like the OnExit method has the best chance to be in the same thread, but even that seems a sketchy assumption. Is there a way to ignore the same-thread requirement? Or should I create and store a separate thread in conjunction with my mutex?
I personally wouldn't bother releasing it at all, especially since you handle AbandonedMutexException.
If a mutex is not used to synchronize threads of the same process there is no need to explicitly release it. When a process terminates OS automatically closes all handles created by the process, such as files, sockets, mutexes, semaphores and event handles .
If you still prefer to release it consider using Application.OnExit() since it is called from the main thread, just like the Startup().
According to my research, every GUI WPF application has a UI thread which can be accessed via Application.Current.Dispatcher (see for example this answer). This UI thread should always remain active for the lifetime of the application.
You can use Dispatcher.CheckAccess to see whether you are running in the UI thread, and if you are not you can use Dispatcher.Invoke to execute an action in the context of the UI thread.
The description of Application.Run implies that Application.OnStartup is always run on the UI thread, but it should not be harmful to check and, if necessary, use the UI thread dispatcher to invoke the action that creates the mutex.
It seems a reasonable guess that Application.OnExit is also always run on the UI thread, but since this does not appear to be documented, you should check and, if necessary, use the UI thread dispatcher to invoke the action that releases the mutex.
As Alexm correctly points out, you do not in fact need to explicitly release the mutex provided that the application is running in its own process (which will usually be the case) but you do need to ensure that the thread the mutex is created on will remain active until you are ready to free it. I believe using the UI thread is the simplest way to ensure this.

Dispatcher.BeginInvoke correct usage?

I am working on understanding how to use BeginInvoke correctly. I wrote up a small test in a console app where all I am trying to do is use BeginInvoke to call a function to make a 100x100 Window with a title pop up. I am failing miserably. Here is what I have, I know this is probably just poor understanding of Threads (not my strong suit), but I'm stuck, no window pops up I just end up at my readline in Main waiting for a keypress. Execution starts at ThreadUITest.
static void ThreadUITest()
{
ThreadStart starter = new ThreadStart(threadFunc1);
Thread test = new Thread(starter);
test.IsBackground = true;
test.SetApartmentState(ApartmentState.STA);
test.Start();
}
static void threadFunc1()
{
dispatcher = Dispatcher.CurrentDispatcher; //Statically declared earlier
ThreadStart starter = new ThreadStart(threadFunc2);
Thread test = new Thread(starter);
test.IsBackground = true;
test.Start();
}
static void threadFunc2()
{
Action method = Draw;
Console.WriteLine("I'm here!");
//dispatcher.BeginInvoke( (Action)(() => {Draw();}),DispatcherPriority.Render, null);
dispatcher.BeginInvoke(method, DispatcherPriority.Send, null);
}
static void Draw()
{
Window win = new Window();
win.Height = 100;
win.Width = 100;
win.Title = "A Window!";
win.Show();
}
Thanks for any help.
You need to add the following at the bottom of your threadFunc1
// statically declared earlier, although you don't need to keep a reference to it as
// WPF will keep it in Application.Current
application = new Application();
application.Run(); // thread1 is now our "UI" thread
Why does this solve it?
The Dispatcher object provides an interface for getting a thread to do some work for you (via BeginInvoke or Invoke).
In order for a thread to be able to process any "do work" messages, it must be running some kind of event loop, where it sits and waits for the next message to process - if it weren't doing this, then it wouldn't be able to process anything, it would just be stuck.
Calling Dispatcher.CurrentDispatcher from thread1 will create a new dispatcher on that thread if there isn't one already there[1] - that gives us our interface to post messages to the thread.
What dispatcher.BeginInvoke does is add an entry into the message queue for that thread, however the thread isn't running any message loop yet. We can queue messages to it, but it won't pick them up and run them - this is why nothing happens.
So, we need to make that thread start running a message loop.
The Application.Run() method is the WPF framework method which does exactly that. The Application.Run method never returns (until you call Application.Shutdown anyway), it starts up a message loop to begin processing messages thereafter. I find it useful to think of it "taking over" the thread.
Now with this change, when thread2func calls dispatcher.BeginInvoke, the message loop code inside Application.Run goes "oh look, a message, I'll process it" - it gets the BeginInvoke method, and does what it's told (in this case, executing your Draw function), and all is well
Note: As per Ark-kun's answer You can also just call Dispatcher.Run to start a message loop on that thread without creating an Application object (Application.Run does this internally). Generally I find it nicer to create an application object though, as that's more "normal", and some other code you may write later on may expect an Application object to exist
[1] FYI, this is why calling Dispatcher.CurrentDispatcher is dangerous and you should avoid it. If you call Dispatcher.CurrentDispatcher from the existing UI thread, it returns you a reference to the correct dispatcher.
If you accidentally call it from another thread, logically, you'd think it would return a reference to the existing dispatcher. But no - instead, it creates a second dispatcher, pointing at our other thread - however our other thread won't be running a message loop, and we'll get stuck again. I'd suggest never calling Dispatcher.CurrentDispatcher except for the very first time.
Once your app is up and running, you generally don't need to do this anyway, as all WPF objects (Window, Button, etc) all have a Dispatcher property which you can use to get the correct dispatcher from anyway
Try calling Dispatcher.Run() in the end of threadFunc1.

How can i run a method in a thread and call a method when the thread exits

I have been searching for an answer to this but cannot find a simple example to help me understand. I am writing win form app in c# that wraps up a bunch of command line tools used for video encoding. I have a method called encodefiles i want to run this method in a thread so that the UI can still operate. Once the thread has finished I want it to call another method so i know it has finished. i can then encode the next file or finish. all depends if there are any more files to encode.
I was getting the action i wanted when i was only running a single command line tool as i was using the process object which you can attach a finished event to. I want to the same for a thread but have no idea how.
In short i want to be able to do the following with a thread instead of a process
Process myProcess = Process.Start(commandLineExe, commandlineSwitches);
myprocess.EnableRaisingEvents = true;
myprocess.Exited += new EventHandler(myprocess_exited);
Hope that makes sense
Am using c# .NET 3.5 with visual studio 2010
well if you are using winforms and you want to run a task in background and notify when its completed use backgroundworker
and handle the DoWork(), WorkerComplete(), progressChanged() events to get your work done.
Did you take a look at the BackgroundWorker class?
It gives you the option to fire 'progress changed' events.
Create one more thread. In the thread procedure for it, do:
yourMonitoredThread.Join();
CallYourProcedure(); // can be event
EDIT:
You can derive from Thread and implement your needed event and use it encapsulated.
Maybe something like this:
public class MyThread
{
Thread _thread;
public MyThread()
{
_thread = new Thread(WorkerMethod);
}
public void Start()
{
_thread.Start();
}
private void WorkerMethod()
{
// do something useful
// [...]
//Exiting this method = exit thread => trigger event
Exited(this, EventArgs.Empty);
}
public event EventHandler Exited = delegate{};
}

Vanishing WindowsForm

I am developing a plugin for an application, that application "consumes" my code (classLibrary), and executes the Init() method inside his own Thread.
Inside the Init() I have a while(true) statement, so that my plugin can run continuously.
Yesterday, I started to make a windowsForm for configuration of my plugin (using XML), and now I want to show it, but it keeps vanishing. My code is as follows:
Doing this will show the form, but, it wont re-paint because it is launched on that same thread as the while(true) is.
MaForm settingsForm = null;
void init(){
While(true){
if(settingsForm == null){
settingsForm = new MaForm();
settingsForm.show();
}
}
}
Version that shows, but then vanishes.
MaForm settingsForm = null;
Thread worker = null;
void init(){
While(true){
if(worker == null){
worker = new Thread(new ThreadStart(formStuff));
worker.Start();
}
}
}
void formStuff()
{
if(settingsForm == null){
settingsForm = new MaForm();
settingsForm.show();
}
}
What am I doing wrong? Is there something about Threading I am missing?
What do you guys think?
The thread is starting, showing your form, then finishing up and shutting down (which closes the form).
Showing a form on a separate thread is nearly always problematic. Forms require a message pump to be running - so they typically will only work properly if they're started and run on the GUI thread.
One option would be to invoke the function to show your form onto your main thread. This will make your form load (and run) on the main thread.
Alternatively, you can start an entire message pump on the form's thread, and set the thread to STA (this is important). However, I suggest avoiding this approach if possible.
you can try this: create the form, enter the infinite loop, call DoEvents() so that your form can process windows messages:
if(settingsForm == null){
settingsForm = new MaForm();
settingsForm.show();
}
while (settingsForm != null && settingsForm.Visible)
{
System.Windows.Forms.Application.DoEvents();
}
EDIT: may be you can replace the true condition by a check on the SettingsForm visibility. When the form is closed, it's a waste to stay in an infinite loop.
A good way of dealing with threading issues in C# is to comment out using System.Threading; at the top of your classes and forms. You may have some compelling reason for showing forms with a Thread, but probably not, since Form.Show() is not a blocking call.
if you're trying to show a form from your Main() method, try using ShowDialog() instead. This call will block until the form is closed.

Categories