C# 识别源线程时出现的问题导致;调用线程必须是STA,因为许多UI组件都需要它;在SkypeKit.NET WPF应用程序中
在我的WPF应用程序开发中,我遇到了一个InvalidOperationException,消息是“调用线程必须是STA,因为许多UI组件都需要STA”。(请参见下面的代码以及发生错误的位置)。错误发生在参与者构造函数内部,因为正在构造画布gui,而画布构造函数本身正在引发此异常,而不是进入构造函数C# 识别源线程时出现的问题导致;调用线程必须是STA,因为许多UI组件都需要它;在SkypeKit.NET WPF应用程序中,c#,.net,wpf,skype,C#,.net,Wpf,Skype,在我的WPF应用程序开发中,我遇到了一个InvalidOperationException,消息是“调用线程必须是STA,因为许多UI组件都需要STA”。(请参见下面的代码以及发生错误的位置)。错误发生在参与者构造函数内部,因为正在构造画布gui,而画布构造函数本身正在引发此异常,而不是进入构造函数 public class Participant : SktParticipant { public enum PictureMode {
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);
我已经阅读了有关STA和MTA线程的内容(例如),但我无法将创建新参与者的线程设置为STA。。当错误发生时,我无法找到调用它的线程/方法。
我已经看到,从以下代码调用参与者构造函数时没有问题:
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(); }
}
我尝试使用各种线程和对象的分派器确定错误的来源,确保main()具有STAthread属性,尝试在看似相关的方法上设置“[STAthread]”
有人知道我如何解决这个错误吗?问题是,在第二种情况下,您的代码由UI线程调用,但在第一种情况下,我认为它是您的工作线程/通信线程之一。在WPF中,所有UI更改必须在UI线程中完成,或者使用特殊的
分派器对象分派给它
将UI更改包装到一个单独的方法中,并使用Application.Current.Dispatcher.Invoke
调用它
这里有一篇关于这个问题及其解决方案的更详细的文章:问题是,在第二种情况下,您的代码由UI线程调用,但在第一种情况下,我假设它是您的工作线程/通信线程之一。在WPF中,所有UI更改必须在UI线程中完成,或者使用特殊的分派器对象分派给它
将UI更改包装到一个单独的方法中,并使用Application.Current.Dispatcher.Invoke
调用它
这里有一篇关于这个问题及其解决方案的更详细的文章:您从哪里实例化参与者
构造函数?另一方面,您必须始终在主线程而不是后台线程上创建UI元素。只需查看调用堆栈调试器窗口,了解您是如何做到这一点的。很可能是由于线程池线程上引发的某种事件。您从何处实例化参与者构造函数?另一方面,您必须始终在主线程而不是后台线程上创建UI元素。只需查看调用堆栈调试器窗口,了解您是如何做到这一点的。很可能是由于在线程池线程上引发的某种事件。