|
|
||||||
|
#1
|
|
|
|
|
Some time ago I needed to write a single-instance app. That's an easy task
but I also needed duplicate instances to pass their command line parameters to the first instance so that it can act upon them. I ended up achieving this using Remoting to start my first app, and then call into that Singleton remoted object from secondary instances. I thought I was pretty clever until today when I tried to show an OpenFileDialog and received an error telling me I have to use my app's main thread. It's proving to be a real pain :-) Does anyone have a solution they have tried? Pete |
|
|
|
#2
|
|
|
|
|
On Thu, 25 Sep 2008 11:58:02 -0700, Peter Morris
<mrpmorrisNO> wrote: > Some time ago I needed to write a single-instance app. That's an easy > task but I also needed duplicate instances to pass their command line > parameters to the first instance so that it can act upon them. > > I ended up achieving this using Remoting to start my first app, and then > call into that Singleton remoted object from secondary instances. I > thought I was pretty clever until today when I tried to show an > OpenFileDialog and received an error telling me I have to use my app's > main thread. [...] Really? That surprises me. Granted, I haven't tried it, and presumably it'd be trivial for me to reproduce the behavior. But dialogs, having their own message loops, usually work okay on any arbitrary thread. That said, given that requirement, why doesn't the standard technique apply? That is, just use Control.Invoke() or similar to execute the code to show the dialog on the correct thread? Pete |
|
#3
|
|
|
|
|
Peter Morris <mrpmorrisNO> wrote:
> Some time ago I needed to write a single-instance app. That's an easy task > but I also needed duplicate instances to pass their command line parameters > to the first instance so that it can act upon them. > > I ended up achieving this using Remoting to start my first app, and then > call into that Singleton remoted object from secondary instances. I thought > I was pretty clever until today when I tried to show an OpenFileDialog and > received an error telling me I have to use my app's main thread. > > It's proving to be a real pain :-) Does anyone have a solution they have > tried? Have you tried using the Microsoft.VisualBasic.ApplicationServices classes? Read http://msdn.microsoft.com/en-us/libr...wx(VS.80).aspx and see if it helps you. Personally I think it would be nice to have this sort of functionality in System.*... |
|
#4
|
|
|
|
|
Yes. Unfortunately it threw a "NotImplemented" or "NotSupported" exception
(don't recall which) on a couple of machines at work, so I abandoned it. |
|
#5
|
|
|
|
|
Peter Morris <mrpmorrisNO> wrote:
> Yes. Unfortunately it threw a "NotImplemented" or "NotSupported" exception > (don't recall which) on a couple of machines at work, so I abandoned it. I suspect it's worth digging into a bit further, as VB.NET uses it pretty easily. It may be worth coming up with a quick VB.NET app then decompiling it to see what it's doing. |
|
#6
|
|
|
|
|
On Thu, 25 Sep 2008 12:09:18 -0700, Peter Duniho
<NpOeStPeAdM> wrote: > [...] >> I ended up achieving this using Remoting to start my first app, and >> then call into that Singleton remoted object from secondary instances. >> I thought I was pretty clever until today when I tried to show an >> OpenFileDialog and received an error telling me I have to use my app's >> main thread. [...] > > Really? That surprises me. Granted, I haven't tried it, and presumably > it'd be trivial for me to reproduce the behavior. But dialogs, having > their own message loops, usually work okay on any arbitrary thread. By the way, I took another look at this, and I can confirm that it's not actually a problem for the OpenFileDialog to be shown on other than the main GUI thread per se. However, the OpenFileDialog does require that the thread be initialized as a COM single-threaded-apartment. Since you're using remoting, you probably don't have control over the nature of the thread itself, and so it might be difficult for you to ensure that. Given that, I still think that my follow-up question still applies: > That said, given that requirement, why doesn't the standard technique > apply? That is, just use Control.Invoke() or similar to execute the > code to show the dialog on the correct thread? Pete |
|
#7
|
|
|
|
|
Hi Pete
Using Invoke doesn't work either..... Thanks for your time! Pete private void ButtonSelectSpeechAudioFileName_Click(object sender, EventArgs e) { Invoke(new System.Threading.ThreadStart( delegate() { OpenFileDialog ofd = GetOpenWavDialog(Composition.SpeechAudioFile); if (ofd.ShowDialog() == DialogResult.OK) Composition.SpeechAudioFile = ofd.FileName; })); } System.Threading.ThreadStateException was unhandled by user code Message="Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process." Source="System.Windows.Forms" StackTrace: at System.Windows.Forms.Control.MarshaledInvoke(Contr ol caller, Delegate method, Object[] args, Boolean synchronous) at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args) at System.Windows.Forms.Control.Invoke(Delegate method) at AlterEgo.WizardStepControls.AudioAndScriptStepCont rol.ButtonSelectSpeechAudioFileName_Click(Object sender, EventArgs e) in C:\Data\CustomerProjects\Inteevo\Projects\AlterEgo \AlterEgo\WizardStepControls\AudioAndScriptStepCon trol.cs:line 77 at System.Windows.Forms.Control.OnClick(EventArgs e) at DevExpress.XtraEditors.BaseButton.OnClick(EventArg s e) at DevExpress.XtraEditors.BaseButton.OnMouseUp(MouseE ventArgs e) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at DevExpress.Utils.Controls.ControlBase.WndProc(Mess age& m) at System.Windows.Forms.Control.ControlNativeWindow.O nMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.W ndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallba ck(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchM essageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager. System.Windows.Forms.UnsafeNativeMethods.IMsoCompo nentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.Run MessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.Run MessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm) at Inteevo.SingleInstanceApp.SingleInstance.Execute(S tring[] args) in C:\Data\CustomerProjects\Inteevo\Libraries\Inteevo .SingleInstanceApp\SingleInstance.cs:line 26 at System.Runtime.Remoting.Messaging.StackBuilderSink ._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink .PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink .SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext) InnerException: |
|
#8
|
|
|
|
|
I did decompile it in the past, pretty deep stuff with use of lots of
classes/methods marked "internal". |
|
#9
|
|
|
|
|
PS: I am going to try named pipes instead of remoting, see if that helps.
Pete |
|
#10
|
|
|
|
|
I adapted this....
[url down] So now I just write new SingleInstanceApplication<MainForm>("MyCompany.MyA pp"); instead of Application.Run(new MainForm()); Works a treat :-) Thanks for your input guys, I appreciate it as always! Pete |
|
#11
|
|
|
|
|
On Fri, 26 Sep 2008 00:17:48 -0700, Peter Morris
<mrpmorrisNO> wrote: > Hi Pete > > Using Invoke doesn't work either..... Your stack trace looks odd. In particular, you seem to be executing your Application.Run() call on a thread without [STAThread]. This will, as the exception implies, cause all sorts of problems. If this is in fact the difficulty you're running into, then I'd say it's a good thing you're running into this problem, because it's one you need to address regardless. Without a concise-but-complete code sample, it's hard to comment on the specific technique you're using to ensure a single-instance application here, but I really don't see any reason that you should have a call to Application.Run() in the same call stack with any of the remoting stuff. By definition, the stuff coming in from remoting should never wind up calling Application.Run()...that's the point of making your application single-instance. Pete |
|
|
| Similar Threads | |
| Multiuse (Single Instance) or Single Use (Multiple Instances) Hi, Some of our VBA application that used createObject doesn't work . Then we found about the below points from Microsoft and made it to work using getObject. "COM servers... |
|
| extract items from list in single field, revisited Hi, Would this also apply to my situation: I need to parse a long text field (imported from a very old database format) which will contain 0 or more 13-character blocks of... |
|
| Single-instance app: how to force running instance window to foreground? I've implemented single-instance functionality in my .exe by using the mutex method. Works great. But when the .exe detects that it is not the first instance I want to... |
|
| Custom Taglib problems - instead of a single instance per page, I have a single instance per application. Hi, What is the correct expected behaviour when using a taglib regarding how many objects are created per page/application? More clearly, I created a custom tag (call it... |
|
| Multi-instance vs single instance application I have a general question. If I write a application using any language(C/C++/C#/VB). How to make sure it only has one instance running? What I need to write in source code?... |
|
|
All times are GMT. The time now is 11:06 PM. | Privacy Policy
|