Created a Windows application consisting of two forms. On the first form, the second is launched. There is one nuance. Before launching the second form, files are copied, which will then be used in the second form. The fact is that during this action, the first form completely freezes. So I decided to use multithreading. To work with files, I created a new background thread. I need to determine the time of its completion in order to run the second form, because if I include the launch of the second form in the same stream as the work with files, it will throw an exception:

"Creating an instance of an ActiveX control" 8856f961-340a-11d0-a96b-00c04fd705a2 "is impossible: the current stream is not in a single-threaded container."

What do you advise me?

  • @VladD can't it be wpf ? - αλεχολυτ
  • @alexolut: "Windows application consisting of two forms ." This is a winforms-specific terminology. Well, the direct use of ActiveX controls (in this case AxWebBrowser) is very similar to WinForms. - VladD
  • @alexolut: While you are right, it could be a WPF problem. I will remove the tag. - VladD

3 answers 3

The specific way how to notify the main form of a thread termination depends on how the thread was called. For example, if you use a BackgroundWorker , which performs a lengthy operation (copying files), then it will signal on completion with the BackgroundWorker.RunWorkerCompleted event. That is, in the calling form, you need to hang up the event handler: when the thread runs, the handler is activated and can start the second thread. The first link in MSDN has a clear example of how to do it correctly.

If the thread is called in some other way, then, in any case, upon its completion, you can signal the event manually, and catch it in the main form.

  • Tell me, is it possible to use several BackgroundWorkers in one application? - grotsun pm
  • one
    Can. Each of them will create its own background thread, and the events about the progress of the operation and its completion will be thrown into the user interface stream. - Modus

In order to check whether the thread is running or has already completed, you can use the property of the Thread object IsAlive. To track this moment, I somehow made an additional background thread (IsBackground = true), which, in a cycle with a period of 100 ms, checked whether the stream of interest to us ended, using this property. Upon completion of this thread, he performed certain actions and completed himself. But then I needed it in order to correctly complete the sidestream at the end of the main; the side stream itself could not be done as a background thread, since it worked with the file system and required correct termination, not a silent interrupt.

In addition, I can offer a method that allows you to work in a single-threaded apartment, regardless of the context of the call.

void Run(ThreadStart doSomething) { if (doSomething == null) throw new ArgumentNullException("doSomething"); if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) doSomething(); else { var th = new Thread(doSomething); th.SetApartmentState(ApartmentState.STA); th.Start(); th.Join(); } } 

That is, if we are already in a single-threaded apartment, simply call the delegate passed through the parameter. If not, create a new stream in a single-threaded apartment and wait for its completion.

  • Thanks for the help! - grotsun

On streams you can wait. WaitForSingleObject ().

  • This works when the synchronization object is known to a thread that is waiting for another thread to complete. - Modus