调用线程必须是STA,因为许多UI组件都需要STA


174

我正在使用http://www.codeproject.com/KB/IP/Facebook_API.aspx

我试图调用使用WPF创建的XAML。但这给了我一个错误:

调用线程必须是STA,因为许多UI组件都需要STA。

我不知道该怎么办。我正在尝试这样做:

FacebookApplication.FacebookFriendsList ffl = new FacebookFriendsList();

但这给了我这个错误。

我添加了一个背景工作者:

static BackgroundWorker bw = new BackgroundWorker();

static void Main(string[] args)
{
    bw.DoWork += bw_DoWork;
    bw.RunWorkerAsync("Message to worker");
    Console.ReadLine();
}

static void bw_DoWork(object sender, DoWorkEventArgs e)
{
    // This is called on the worker thread
    FacebookApplication.FacebookFriendsList ffl = new FacebookFriendsList();

    Console.WriteLine(e.Argument);        // Writes "Message to worker"

    // Perform time-consuming task...
}

Answers:


222

尝试从调度程序调用您的代码:

Application.Current.Dispatcher.Invoke((Action)delegate{
      // your code
});

是的,你们救了我的命!!
Alex McManns '16

11
这是真正的答案。您可以以此来消除WPF的窗口愚蠢性。
安德鲁

7
与此类似,如果您碰巧正在使用MVVMLight,则可以使用DispatcherHelper.CheckBeginInvokeOnUI(Action action)
TimothyP,2016年

这个问题看起来很复杂而且令人沮丧,但是这张照片真的很棒!非常感谢 !
凯李

4
@Andrew这不是愚蠢,您只是尝试从后台线程访问UI线程。
Krusty

139

如果从主线程进行调用,则必须将STAThread属性添加到Main方法中,如上一个答案所述。

如果使用单独的线程,则它必须位于STA(单线程单元)中,而后台工作线程则不是这种情况。您必须自己创建线程,如下所示:

Thread t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);

t.Start();

ThreadProc是ThreadStart类型的委托。


2
(使用STA)可能会产生副作用吗?
路易·瑞斯

10
成为STA的主要副作用是同时COM回调被序列化。如果您不使用COM回调,那没关系。
Timores 2012年

救了我一命!能够在承载了本地API的WPF应用程序中使用此功能,以实现两个不同应用程序之间的集成!
schizoid04

18

您也可以尝试

// create a thread  
Thread newWindowThread = new Thread(new ThreadStart(() =>  
{  
    // create and show the window
    FaxImageLoad obj = new FaxImageLoad(destination);  
    obj.Show();  

    // start the Dispatcher processing  
    System.Windows.Threading.Dispatcher.Run();  
}));  

// set the apartment state  
newWindowThread.SetApartmentState(ApartmentState.STA);  

// make the thread a background thread  
newWindowThread.IsBackground = true;  

// start the thread  
newWindowThread.Start();  

谢谢。当使用Applicationcontext类而不是Form时,这将有所帮助。
萨达姆·宾赛德(SaddamBinSyed)

当我像在其他许多地方一样单击按钮时,我正在打开一个新表单。知道为什么只有这些地方之一引发此错误吗?
Paul McCarthy

17

我怀疑您正在从后台线程获取对UI组件的回调。我建议您使用BackgroundWorker进行该调用,因为它可以识别UI线程。

对于BackgroundWorker,主程序应标记为[STAThread]。


1
我尝试添加它,如上所述,但它仍然给我错误:/
C..2010年

我对代码不熟悉。您能否调试并准确找出导致此问题的代码行?
Preet Sangha 2010年

3

只要用[STAThread]属性标记您的程序,错误就会消失!这是魔法 :)


1

对我来说,发生此错误是因为传递了空参数。检查变量值可以解决我的问题,而无需更改代码。我使用了BackgroundWorker。


-3

如果您在现有线程中调用新的窗口UI语句,则会引发错误。取而代之的是在主线程内创建一个新线程,然后在新的子线程中编写window UI语句。


请问如何写解释?
Tushar Gupta-curioustushar
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.