Reputation: 70404
I have a form that starts a thread. Now I want the form to auto-close when this thread terminates.
The only solution I found so far is adding a timer to the form and check if thread is alive on every tick. But I want to know if there is a better way to do that?
Currently my code looks more less like this
partial class SyncForm : Form {
Thread tr;
public SyncForm()
{
InitializeComponent();
}
void SyncForm_Load(object sender, EventArgs e)
{
thread = new Thread(new ThreadStart(Synchronize));
thread.IsBackground = true;
thread.Start();
threadTimer.Start();
}
void threadTimer_Tick(object sender, EventArgs e)
{
if (!thread.IsAlive)
{
Close();
}
}
void Synchronize()
{
// code here
}
}
Upvotes: 8
Views: 14456
Reputation: 8986
Solution for arbitrary thread (e.g. started by some other code), using UnmanagedThreadUtils package:
// Use static field to make sure that delegate is alive.
private static readonly UnmanagedThread.ThreadExitCallback ThreadExitCallbackDelegate = OnThreadExit;
public static void Main()
{
var threadExitCallbackDelegatePtr = Marshal.GetFunctionPointerForDelegate(ThreadExitCallbackDelegate);
var callbackId = UnmanagedThread.SetThreadExitCallback(threadExitCallbackDelegatePtr);
for (var i = 1; i <= ThreadCount; i++)
{
var threadLocalVal = i;
var thread = new Thread(_ =>
{
Console.WriteLine($"Managed thread #{threadLocalVal} started.");
UnmanagedThread.EnableCurrentThreadExitEvent(callbackId, new IntPtr(threadLocalVal));
});
thread.Start();
}
UnmanagedThread.RemoveThreadExitCallback(callbackId);
}
private static void OnThreadExit(IntPtr data)
{
Console.WriteLine($"Unmanaged thread #{data.ToInt64()} is exiting.");
}
Upvotes: 0
Reputation: 171734
At the end of your thread method, you can call Close() using the Invoke() method (because most WinForms methods should be called from the UI thread):
public void Synchronize()
{
Invoke(new MethodInvoker(Close));
}
Upvotes: 1
Reputation: 18760
If you have a look at a BackgroundWorker, there is a RunWorkerCompleted event that is called when the worker completes.
For more info on BackgroundWorkers Click Here
Or
You could add a call to a complete function from the Thread once it has finished, and invoke it.
void Synchronize()
{
//DoWork();
//FinishedWork();
}
void FinishedWork()
{
if (InvokeRequired == true)
{
//Invoke
}
else
{
//Close
}
}
Upvotes: 6
Reputation: 166326
Have a look at delegates, IAsyncResult, BeginInvoke and AsyncCallback
Upvotes: 1
Reputation: 99859
Edit to make it call a helper method so it's cleaner.
thread = new Thread(() => { Synchronize(); OnWorkComplete(); });
...
private void OnWorkComplete()
{
Close();
}
Upvotes: 6
Reputation: 11277
The BackgroundWorker class exists for this sort of thread management to save you having to roll your own; it offers a RunWorkerCompleted event which you can just listen for.
Upvotes: 12