Wątkiem wywołującym musi być STA, ponieważ wymaga tego wiele składników interfejsu użytkownika

174

Używam http://www.codeproject.com/KB/IP/Facebook_API.aspx

Próbuję wywołać XAML, który jest tworzony przy użyciu WPF . Ale daje mi błąd:

Wątkiem wywołującym musi być STA, ponieważ wymaga tego wiele składników interfejsu użytkownika.

Nie wiem co mam robić. Próbuję to zrobić:

FacebookApplication.FacebookFriendsList ffl = new FacebookFriendsList();

Ale to daje mi ten błąd.

Dodałem pracownika w tle:

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...
}
DO..
źródło

Odpowiedzi:

222

Spróbuj wywołać swój kod z dyspozytora :

Application.Current.Dispatcher.Invoke((Action)delegate{
      // your code
});
Amjad Abdelrahman
źródło
Yeahhh, uratowaliście mi życie !!
Alex McManns
11
To jest prawdziwa odpowiedź. Dzięki temu możesz odhakować głupotę okien WPF.
Andrew,
7
I podobnie do tego, jeśli używasz MVVMLight, możesz użyćDispatcherHelper.CheckBeginInvokeOnUI(Action action)
TimothyP
Ten problem wydawał się skomplikowany i sfrustrowany, ale to ujęcie jest naprawdę fajne! Dziękuję bardzo !
Kay Lee
4
@Andrew To nie jest głupota, po prostu próbujesz uzyskać dostęp do wątku interfejsu użytkownika z wątku w tle.
Krusty
139

Jeśli wykonujesz wywołanie z głównego wątku, musisz dodać atrybut STAThread do metody Main, jak stwierdzono w poprzedniej odpowiedzi.

Jeśli używasz oddzielnego wątku, musi on znajdować się w STA (mieszkaniu jednowątkowym), co nie ma miejsca w przypadku wątków roboczych w tle. Musisz sam stworzyć wątek, w ten sposób:

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

t.Start();

z ThreadProc będącym delegatem typu ThreadStart.

Timory
źródło
2
czy to (używając STA) może mieć efekt uboczny?
Louis Rhys
10
Głównym efektem ubocznym bycia STA jest to, że jednoczesne wywołania zwrotne COM są serializowane. Jeśli nie używasz wywołań zwrotnych COM, nie powinno to mieć znaczenia.
Timores
Uratował mi życie! Był w stanie użyć tego w aplikacji WPF, która hostowała lokalny interfejs API do integracji między dwiema różnymi aplikacjami!
schizoid04
18

Możesz także spróbować tego

// 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();  
atik sarker
źródło
Dzięki. Pomoże to w przypadku używania klasy Applicationcontext zamiast Form.
SaddamBinSyed
Otwieram nowy formularz po kliknięciu przycisku, tak jak robię to w wielu innych miejscach. Masz jakiś pomysł, dlaczego tylko jedno z tych miejsc rzuca ten błąd?
Paul McCarthy
17

Podejrzewam, że otrzymujesz wywołanie zwrotne do składnika interfejsu użytkownika z wątku w tle. Zalecam wykonanie tego wywołania przy użyciu BackgroundWorker, ponieważ jest to świadomy wątek interfejsu użytkownika.

W przypadku BackgroundWorker główny program powinien być oznaczony jako [STAThread].

Preet Sangha
źródło
1
Próbowałem go dodać jak wyżej, ale nadal daje mi błąd: /
C ..
Nie znam kodu. Czy możesz przeprowadzić debugowanie i znaleźć dokładną linię kodu, która to powoduje?
Preet Sangha
3

Po prostu oznacz swój program [STAThread]atrybutem, a błąd zniknie! to magia :)

LiRoN
źródło
1

U mnie ten błąd wystąpił z powodu przekazania parametru o wartości null. Sprawdzanie wartości zmiennych rozwiązało mój problem bez konieczności zmiany kodu. Użyłem BackgroundWorker.

Ryan Loggerythm
źródło
-3

Jeśli wywołasz instrukcję interfejsu użytkownika nowego okna w istniejącym wątku, zgłosi błąd. Zamiast tego utwórz nowy wątek w głównym wątku i napisz instrukcję interfejsu użytkownika okna w nowym wątku podrzędnym.

Balvant Ramani
źródło
jak napisać pls wyjaśnić?
Tushar Gupta - curioustushar