It seems to me that you are working with at least one false assumption.
1. You do not need to raise a ProgressChanged event to have a responsive interface
In your question you say the following:
BackgroundWorker is not an answer because it may be that I am not receiving a progress notification, which means there would be no call to ProgressChanged as DoWork is one call to an external function.,.
Actually, it doesn't matter if you raise the ProgressChanged event or not . The whole purpose of this event is to temporarily transfer control back to the GUI thread to make an update that somehow reflects the progress of the work that BackgroundWorker is doing. If you just show the marquee progress bar, it would actually be pointless to raise the ProgressChanged event at all . The progress bar will continue to rotate while being displayed because BackgroundWorker is doing its work on a separate thread from the GUI .
(On the side, the DoWork note is an event, which means it's not just “one call to an external function”; you can add as many handlers as you want, and each of these handlers can contain as many function calls as he likes.)
2. You do not need to call Application.DoEvents to have a responsive interface
It seems to me that you think that the only way to update the GUI is to call Application.DoEvents :
I need to keep calling Application.DoEvents (); for progress bar to continue rotation.
This is not true in a multi-threaded scenario ; if you use BackgroundWorker , the GUI will continue to respond (in its own thread), and BackgroundWorker does everything that was attached to its DoWork event. Below is a simple example of how this might work for you.
private void ShowProgressFormWhileBackgroundWorkerRuns() { // this is your presumably long-running method Action<string, string> exec = DoSomethingLongAndNotReturnAnyNotification; ProgressForm p = new ProgressForm(this); BackgroundWorker b = new BackgroundWorker(); // set the worker to call your long-running method b.DoWork += (object sender, DoWorkEventArgs e) => { exec.Invoke(path, parameters); }; // set the worker to close your progress form when it completed b.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) => { if (p != null && p.Visible) p.Close(); }; // now actually show the form p.Show(); // this only tells your BackgroundWorker to START working; // the current (ie, GUI) thread will immediately continue, // which means your progress bar will update, the window // will continue firing button click events and all that // good stuff b.RunWorkerAsync(); }
3. You cannot run two methods simultaneously in the same thread
You say this:
I just need to call Application.DoEvents () so that the Marque Indicator will work while the working function is working basically the thread.,.
What you are asking for is simply not real . The "main" thread for a Windows Forms application is a GUI thread that, if busy with your long-term method, does not provide visual updates. If you think otherwise, I suspect that you misunderstood what BeginInvoke doing: it starts the delegate in a separate thread . In fact, the sample code that you included in your question to call Application.DoEvents between exec.BeginInvoke and exec.EndInvoke is redundant; you are actually calling Application.DoEvents from the GUI thread , which will be updated anyway . (If you find otherwise, I suspect this because you immediately called exec.EndInvoke , which blocked the current thread until the method completed.)
So yes, the answer you are looking for is to use BackgroundWorker .
You can use BeginInvoke , but instead of calling EndInvoke from the GUI thread (which will block it if this method is not finished), pass the AsyncCallback parameter to your BeginInvoke call (instead just pass null ) and close the execution form in your callback. However, keep in mind that if you do this, you will have to call a method that closes the progress form from the GUI thread, because otherwise you will try to close the form, which is a GUI function, from the stream without a GUI. But in fact, all the problems with using BeginInvoke / EndInvoke have already been considered for you with the BackgroundWorker class, even if you think this is "magic .NET code" (for me it is just an intuitive and useful tool).