Click here to Skip to main content
15,891,864 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
If I try to create a C# class library that shows a form with a webbrowser in it, the execution of the library shows the error: System.Threading.ThreadStateException: ActiveX control, and it does not allow to show the form and the application ends.

I have a console application made in C++, which loads a C# class library, which, when started, should show a form with a webbrowser in it, but when executing the code to show the form the application shows the previous error and finish.

I believe that the unmanaged package using RGiesecke.DllExport is incompatible with the normal threads of an application

What I have tried:

I try:

C#
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class MainModule
{
    [DllExport(ExportName = "ObjectWebJS", CallingConvention =
    CallingConvention.StdCall)]
    static public int ObjectWebJS(int a, int b)
    {
        LoadForm();
        return 0;
    }
    [STAThread]
    public static void LoadForm()
    {
        ObjectForm form1 = new ObjectForm();
        form1.ShowDialog();
    }
}
Posted
Updated 23-Nov-18 2:17am
v3
Comments
KarstenK 23-Nov-18 2:08am    
The reason is that to show an UI the executing thread needs that rights. An app has this rights - but not a dll.
fisadmaster 23-Nov-18 4:45am    
Thanks for the comment but you are wrong because when I do not use the RGiesecke package the C# class library works as it should and I can load it from a console application in C++ and show the form with the webbrowser.

What I understand is that the RGiesecke package causes the C# class library to run on a multi thread and that is incompatible with the webbrowser component.

1 solution

Apply this attribute to the entry point method (the Main() method in C# and Visual Basic). It has no effect on other methods.

Your calling code is in an MTA thread. Applying the [STAThread] attribute to the method it calls will have no effect.

You need to test the current thread's apartment state, and spin up a new STA thread if necessary.
C#
public static void LoadForm()
{
    if (Thread.CurrentThread.ApartmentState == ApartmentState.STA)
    {
        LoadFormCore();
    }
    else
    {
        ThreadStart run = LoadFormCore;
        Thread t = new Thread(run);
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        t.Join();
    }
}

private static void LoadFormCore()
{
    ObjectForm form1 = new ObjectForm();
    form1.ShowDialog();
}
 
Share this answer
 
Comments
fisadmaster 23-Nov-18 8:51am    
Thanks your proposal works perfect

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900