views:

32

answers:

2

The client and server of my program are both marked STAThread, and I verified in the debugger that the thread I make the call from is marked as STA. On the server side, I verified that the program itself when setting up the server is marked STA. However the actual .Net remoting call is done via a thread which is marked MTA. Is there anyway to change this behavior as my service method accesses resources which require an STA thread.

A: 

You can create another thread and mark it as STA to read the resources. I assume it is not going to be used to access COM objects and so on. In that case, it should be ok, but there is an overhead of creating this additional thread.

Saravanan
I tried that, and it is failing to set the apartment state on the thread I created.
esac
A: 

Remoting cannot do this, a hard requirement for an STA thread is that it also pumps a message loop. You'll indeed have to create your own thread, use Thread.SetApartmentState() to switch it to STA before you start it. And use Application.Run() with a dummy form to start the message loop. You can then use Control.BeginInvoke() to marshal the call from the remoting thread to this new thread.

Note that since you already started an STA thread for the server, that thread would do the job just fine. Paste this into your form class to prevent it from getting visible:

    protected override void SetVisibleCore(bool value) {
        if (!this.IsHandleCreated) {
            this.CreateHandle();
            value = false;
        }
        base.SetVisibleCore(value);
    }
Hans Passant
I tried this, unless I am doing it wrong. Inside of my Program's Main which is decorated with [STAThread] I ran Application.Run(dummyForm); on the dummy form I created with your override above. Then I created a stub method as LaunchViaMainThread(Action action) { Program.DummyForm.BeginInvoke(action); }. I then of course call this via myProxyInstance.LaunchViaMainThread(myProxyInstance.Run); from my client. I still see the thread as being marked as MTA when I get into myProxyInstance.Run.
esac
I dunno, should work of course. Add some logging, display Thread.CurrentThread's ManagedId and GetApartmentState() in the main thread and the invoked callback.
Hans Passant
And double-check that Program.DummyForm.InvokeRequired is true.
Hans Passant
And double-check that SetVisibleCore is actually being called.
Hans Passant
Still not any luck. InvokeRequired is returning true. SetVisibleCore is getting called. My log shows the program itself running on Thread Id 1 with STA. Then it shows my method which I call via BeginInvoke as happening on Thread 8 with Apartment MTA.
esac
Well, everything checks out, the BeginInvoke call would run the delegate target on thread 1 which is STA. The only other possibility is that BeginInvoke would use a threadpool thread to run the target in which case you'd see another thread id.
Hans Passant
Oh, and make *very* sure that you use the dummy form's BeginInvoke method, not the delegate's.
Hans Passant
Yep, using the dummy forms BeginInvoke method, but the calls are obviously happening on a separate thread. No idea here :(
esac
It works, the problem is the helper method I wrote to pass it as a delegate instead. When I call DummyForm.BeginInvoke((Action)MyMehtod) instead, it works. Go figure.
esac