2012-11-23 82 views
1

我遇到了InvalidOperationException異常,並顯示消息「調用線程必須是STA,因爲許多UI組件都需要這個。」在我的WPF應用程序開發中。 (請參閱下面的代碼和發生錯誤的位置)。該錯誤發生在Participant構造函數內部,因爲Canvas gui正在被構造,並且Canvas構造函數本身拋出這個異常,而不是進入構造函數。標識源線程導致的問題「調用線程必須是STA,因爲許多UI組件都需要這個。」在SkypeKit.NET WPF應用程序中

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線程(如"The calling thread must be STA, because many UI components require this." WPF),但我不能設置它創建了一個新的參與者到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(); } 
     } 

我試圖拖住其中的錯誤是從哪裏來的,使用各種主題和對象的調度,確保主()具有STAthread屬性,嘗試在看似相關的方法上設置「[STAThread]」。

有人知道我該如何解決這個錯誤嗎?

+0

從你在哪裏實例化'Participant'構造?在旁註中,您必須始終在主線程上創建UI元素,而不是後臺線程。 –

+0

只需查看Call Stack調試器窗口,即可瞭解如何到達那裏。很可能是由於線程池線程中引發的某種事件。 –

回答

1

問題是,在第二種情況下,您的代碼由UI線程調用,但在第一種情況下,我認爲它是您的工作/通信線程之一。在WPF中,所有UI更改都必須在UI線程中完成,或者使用特殊的Dispatcher對象分派給它。

將UI更改包裝爲單獨的方法,並使用Application.Current.Dispatcher.Invoke來調用它。

這裏有一個關於這個問題,它的解決方案更詳細的文章:http://blog.decarufel.net/2009/03/good-practice-to-use-dispatcher-in-wpf.html

相關問題