I'm encountering an InvalidOperationException with the message "The calling thread must be STA, because many UI components require this." in my WPF application development. (See below the code with the location where the error is happening). The error happens inside Participant constructor, as Canvas gui is being constructed and the Canvas constructor itself is throwing this exception, not entering the constructor.
public class Participant : SktParticipant
{
public enum PictureMode
{
Avatar,
Video
}
public PictureMode pictureMode = PictureMode.Avatar;
public Canvas gui;
public VerticalProgressBar voiceVolume;
public Label nameLabel;
public VideoRenderer pic;
public Video video;
public bool isCachedInClient = false; // indicates whether displayName and avatarImage have values
public string displayName = null;
public Image avatarImage = null;
public int picHeight = 480;
public int piclWidth = 640;
public int panelHeight = 155;
public int panelWidth = 174;
public System.Drawing.Color liveColor = System.Drawing.SystemColors.GradientActiveCaption;
public System.Drawing.Color nonLiveColor = System.Drawing.SystemColors.GradientActiveCaption;
public Participant(uint objectId, SktSkype skype)
: base(objectId, skype)
{
gui = new Canvas() //HERE IS THE InvalidOperationException ERROR
{
Width = panelWidth,
Height = panelHeight,
//BorderStyle = BorderStyle.FixedSingle,
Background = System.Windows.SystemColors.GradientActiveCaptionBrush
};
pic = new VideoRenderer(skypeRef)
{
Margin = new System.Windows.Thickness { Left = 5, Top = 5, Right = 0, Bottom = 0 },
Height = picHeight,
Width = piclWidth,
Stretch = Stretch.Fill
};
gui.Children.Add(pic);
I've read about STA and MTA threading (e.g. "The calling thread must be STA, because many UI components require this." WPF), but I can't set the thread which creates a new Participant to STA.. I’ve not been able to locate which is the thread / method that is calling it, when the error occurs. I’ve seen that the Participant contructor is called with no problems from the following code:
private void callButton_Click(object sender, EventArgs e)
{
if (liveSession != null)
{
if ((liveSession.P_LOCAL_LIVESTATUS == SktConversation.LOCAL_LIVESTATUS.RINGING_FOR_ME) ||
(liveSession.P_LOCAL_LIVESTATUS == SktConversation.LOCAL_LIVESTATUS.OTHERS_ARE_LIVE))
{
liveSession.JoinLiveSession("");
}
else
{
if (liveSession == null) return;
// if we leave volountarily, while other people are still in a live session,
// the liveSession P_LOCAL_LIVESTATUS will remain OTHERS_ARE_LIVE.
// So, we need to switch UI mode to not-yet-in-call state here as well.
liveSession.LeaveLiveSession(false);
liveSession = null;
ReleaseWebcam();
UiToWaitingMode();
}
return;
}
if (convListBox.SelectedItem == null) return;
// Here we actually make the outgoing call
Conversation conv = (Conversation)convListBox.Items[convListBox.SelectedIndex];
liveSession = conv;
// Fetching target list from conv and converting to string list
SktParticipant.List parts;
parts = liveSession.GetParticipants(SktConversation.PARTICIPANTFILTER.OTHER_CONSUMERS);
foreach (Participant p in parts) { p.RingIt(); }
}
I've tried to pin down where the error is coming from, using dispatchers of various threads and objects, ensured main() has STAthread attribute, tried setting "[STAThread]" on seemingly relevant methods.
Does somebody know how I can solve this error?
Participant
constructor? On a side note you must always create UI elements on Main thread instead of background thread. – Rohit Vats