Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

I created a simple new Windows Form project in VS2005 Sp1 (C#), and all the form does is have a button that opens a VB6 COM object, which also has a form. The problem is, when I move the top VB6 form around and over the .NET form, the button on the .NET form disappears and doesn't come back.

 

I will post a series of screenshots to demonstrate.

 

Once I close the VB6 form, then the button returns.

 

Any ideas? I am new to .NET forms programming - hopefully its something simple.

 

Thanks.

Posted

Just wanted to add a follow-up comment. This only happens when I put up a VB6 form in front of it. If I put up another .NET form this does not occur. But I still have the problem as I do not want to rewrite my VB6 code yet.

 

Thanks.

Posted

Threading

 

As a guess, I would say that the VB6 COM object is launched on the UI thread of the .Net process, meaning the .Net form cannot respond to window messages (such as a paint message). To overcome this, you could try launching the COM object on a different thread.

 

Imports System.Threading


Private Sub ThreadProc(ByVal state As Object)
   'Code to start VB6 COM object
End Sub

Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
   'Call ThreadProc on a seperate thread (using ThreadPool)
   ThreadPool.QueueUserWorkItem(AddressOf ThreadProc)
End Sub

 

If the COM object is to be displayed modally (so that the .Net form cannot be used) then you can disable the .Net form while the COM object is shown and then enable it again afterwards.

 

Good luck :cool:

Never trouble another for what you can do for yourself.
Posted

I am trying to implement this threading suggestion. I got it halfway working (the thread starts and the form distortion is gone) - but I need the originating thread to stop working until my VB6 thread is done. I am trying to implement a Mutex, but I am having no success. Here is the code, what am I doing wrong? (Note that I tried both ThreadPool.QueueUserWorkItem, and a simple Thread.Start)

 

private static Mutex mut = new Mutex();
private void btnMEU_Click(object sender, EventArgs e)
       {
           // Queue the task.
           //ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
           Thread myThread = new Thread(new ThreadStart(ThreadProc));
           myThread.Start();
           
// Allow new thread to start and claim mutex
           Thread.Sleep(1000);
// Now wait for the mutex to be released
           mut.WaitOne();

       }

       // This thread procedure performs the task.
       private static void ThreadProc()
       {
// Claim the mutex so the originating thread has to wait
           mut.WaitOne();
// Do my work

// Release the mutex
           mut.ReleaseMutex();
       }

Posted

We may have to scratch that theory completely - I just tried bringing up another VB6 COM form, and this time the distortion appears on my COM form! Note the weird black boxes. (see attachment) This form shows up fine when I open it from a VB6 project.

Here is the code that brings up that COM object (it is included as a Reference obviously):

        private void btnMEU_Click(object sender, EventArgs e)
       {
           ModelExtractorUtility.Launcher meu = new ModelExtractorUtility.Launcher();
           meu.ApplicationID = Singleton.Instance.ApplicationID;
           meu.LogCfgFile = Singleton.Instance.LogCfgFile;
           meu.WorkingDirectory = Singleton.Instance.WorkingDirectory;
           meu.Launch();
           }

 

Could this still be a threading issue?

Posted

Mutex bad, Invoke good!

 

Regarding the code which uses a Mutex, this is not the correct way to solve the problem - the original issue with the button not redrawing was because the UI thread (responsible for the drawing) was being tied up by the COM object. Causing it to wait on a Mutex is no better - while the UI thread is waiting it will be unable to handle drawing or other messages.

 

A much better approach would be to invoke a delegate once the 'work' has been completed. The Form has an Invoke method which will call the specified delegate on the UI thread. So, your code might look something like:

 

private delegate void WorkCompletedHandler();

private void btnMEU_Click(object sender, EventArgs e)
{
   //Queue the task.
   ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
   //Disable the form
   this.Enabled = false;
}

private void WorkCompleted()
{
   //Peform final processing

   //Enable the form
   this.Enabled = true;
}

// This thread procedure performs the task.
private static void ThreadProc(object status)
{
   //Do my work

   //Invoke WorkCompleted on UI thread to signal work is complete
   this.Invoke(new WorkCompletedHandler(WorkCompleted));
}

 

Alternatively, you could just use the BackgroundWorker form component, which handles the intricacies of threading for you.

 

As far as your latest issue is concerned, I suppose it is possible that it is another threading issue, but that seems unlikely. Does the COM form remain responsive to input, despite the black boxes?

Never trouble another for what you can do for yourself.
Posted

This method seems to have done the trick. Other then having to remove the "static" key word from the ThreadProc declaration (can't use "this" in static method), it worked just as written.

 

I tried it in both situations, and they appear to be working now with no draw problems.

 

Thanks!!!!

 

Here is the final code.

        private delegate void WorkCompletedHandler();

       private void WorkCompleted()
       {
           //Peform final processing
           Singleton.Instance.InitLogging();
           Singleton.Instance.LogFlow("Returning from COM app");

           //Enable the form
           this.Enabled = true;
       }

       private void btnMEU_Click(object sender, EventArgs e)
       {
           Singleton.Instance.LogFlow("Starting COM app");
           Singleton.Instance.TermLogging();

           // Queue the task.
           ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
           this.Enabled = false;
           }

       private void ThreadProc(object state)
       {
           ModelExtractorUtility.Launcher meu = new ModelExtractorUtility.Launcher();
           meu.ApplicationID = Singleton.Instance.ApplicationID;
           meu.LogCfgFile = Singleton.Instance.LogCfgFile;
           meu.WorkingDirectory = Singleton.Instance.WorkingDirectory;
           meu.Launch();

           this.Invoke(new WorkCompletedHandler(WorkCompleted));
       }

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...