[SOLVED] How to INVOKE a method in the main thread?

Hi there,

I’ve created a separated thread to load the content (textures, songs, etc) and it works well but now I need to set some text in the clipboard using the following statement

Clipboard.SetText("test");

from that separated thread and of course I get this exception

An exception of type ‘System.Threading.ThreadStateException’ occurred in System.Windows.Forms.dll but was not handled in user code

Additional information: 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.

The problem here is that I don’t know how to access to the main thread to do an Invoke() or BeginInvoke() in the main thread.

Can anyone help me please?

Are you using winforms or XAML ?
The update of the UI from a thread is a little different (invoke with forms, dispatcher with XAML)

EDIT: I just saw the part “occurred in System.Windows.Forms.dll”

So to make this:

delegate void setTextCallBack(Control c, string txt);

public void SetText(Control c, string txt)
{
	if(c != null)
	{
		if(c.InvokeRequired)
		{
			c.Invoke(new setTextCallBack(SetText), new object[] { c, txt });
		}
		else
			c.Text = txt;
	}
}

And you call SetText from your thread.
Be warned this does not check if the control has a Text property. You can directly replace “c” with the control object if you prefer (and update the method and delegate accordingly)
I dunno if this should work to set text to the clipboard, if the clipboard is an OLE element.

I don’t know which one I’m using. I just created a new game using “Monogame Windows Project” (DirectX) template in Visual Studio.

To be able to use Clipboard.SetText(string) I’m using System.Windows.Form namespace but I don’t have any Form in the game. It’s a DX full screen game.

In your example you’re using Invoke with a control but like I said before I don’t have any control nor any form in the game so would you please show me an example using SetClipboard?

Thank you

So if I have understood, you try to pass text/data from the game’s thread to the clipboard ? I thought you were making a sort of editor.

I’m trying to pass some text to the clipboard from a thread different than the game’s thread. That’s why I’m asking how to get the game’s thread.

I need to set the text “Test” to the clipboard. The way I know to do that is using the statement SetClipboard(“Test”) but if it must be done using some workaround it’s OK.

First, you should use

if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
{
//do something with the clipboard
}

Second, I’m sure this can be done from another thread than the main one with a clipboard as I said in my first answer.

Do you have to handle some text between game and OS ?

It’s equals to ApartmentState.MTA

Here’s my code:

public class Game1 : Game
{
    protected override void LoadContent()
    {
    	Task.Factory.StartNew(LoadGame);
    }

    void LoadGame()
    {
    	var gas = Thread.CurrentThread.GetApartmentState();
    	if (gas == ApartmentState.STA) // false (gas == ApartmentState.MTA)
    	{
    		Clipboard.SetText("test");
    	}
    }
}

Your thread has to be STA to use the clipboard

What should I do?

That’s why I’m trying to do an Invoke(...) from the main thread (which is STA!) but I don’t know how to get access to it.

When creating a thread and before the .Start() call, you need to call mythread.SetApartmentState(ApartmentState.MTA);

Look here for explanations :wink:

From .net - Could you explain STA and MTA? - Stack Overflow

The COM threading model is called an “apartment” model, where the execution context of initialized COM objects is associated with either a single thread (Single Thread Apartment) or many threads (Multi Thread Apartment). In this model, a COM object, once initialized in an apartment, is part of that apartment for the duration of it’s runtime.

The STA model is used for COM objects that are not thread safe. That means they do not handle their own synchronization. A common use of this is a UI component. So if another thread needs to interact with the object (such as pushing a button in a form) then the message is marshalled onto the STA thread. The windows forms message pumping system is an example of this.

If the COM object can handle its own synchronization then the MTA model can be used where multiple threads are allowed to interact with the object without marshalled calls.

1 Like

It works now!

Thank you for your help :slight_smile:

Glad I could help :slight_smile:
Note that threads created with the Thread class are somewhat obsolete.
Give a preference to Task when possible. Or any of the new threading possibilities with C# 4.x (async, await…)

1 Like

hi
What was the final solution?
please paste your code.