To pytanie jest związane z najwyżej ocenianym komentarz To pytanie:

Model Sta jest używany do obiektów COM, które nie są bezpieczne. Oznacza to, że nie obsługują własnej synchronizacji. Powszechne użycie jest komponentem UI. Jeśli więc inny wątek musi wchodzić w interakcję z obiektem (taki jak naciśnięcie przycisku w formularzu), komunikat jest przechowywany na wątku STA. System pompowania wiadomości systemu Windows jest przykładem tego.

Więc następujący przykład mnie mylą.

Main jest opatrzone za pomocą [STAThread].

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

Przypadkowałem się, że, ponieważ Form1 biegnie w StathRead, każda wiadomość do składnika interfejsu interfejsu użytkownika wysyłana z innego wątku jest marszcząca na wątek STA.

Dlatego się spodziewałem, że wezwanie tak jakby to działało:

public Form1()
{
    InitializeComponent();

    Thread t = new Thread(() => { this.label1.Text = "test"; });
    t.IsBackground = true;
    t.Start();
}

Jak omówiono w wielu innych postach, nie zadziała. Thread t ... musi być zastąpiony czymś takim jak Thread t = new Thread(()=> { this.label1.Invoke((Action)(() => { this.label1.Text = "test"; })); });, aby go naprawić, ale mając na uwadze, że sta powinna marszałkować {{x2} Błąd dostępu?

Edytuj rozwiązany:

Akceptowana odpowiedź:

[STAThread] (i {x1}}) są związane tylko z pracą z COM Interop.

Ponieważ obiekt etykiet wydaje się być tylko owijką dla kontroli Win32, nie jest obiektem COM (jak błędnie oczekiwano ode mnie ze względu na blokadę na początku pytania), a więc połączenia nie będą ustalane. Istnieją sprawdzanie połączeń z innych wątków wewnątrz opakowania, ale marshalling przez (rozpocznij) należy wykonać przez dewelopera.

Oczywiście nadchodzi pytanie: W jaki sposób można modyfikować owijkę, więc odbywa się to automatycznie i zgodne z w dół .. Ale to jest inny temat, chyba.

2
ChrisG 15 luty 2017, 15:07

2 odpowiedzi

Najlepsza odpowiedź

Domyślnie obiekty .NET nie ma żadnego rodzaju marszałkowania wielu wątków.

[STAThread] (i {x1}}) są związane tylko z pracą z COM Interop. Ogólnie te atrybuty instruuje, jak zainicjować wątek przez COINITIALIZEEX zadzwoń. Tak prawdziwe marshalling wydarzy się tylko podczas uzyskiwania dostępu do obiektów COM i zostanie wykonana przez podsystem COM, a nie .NET.

Ui jest inną bestią. Właściwie większość elementów sterujących Win32, które używane pod maską są sejf (ponieważ są one oparte na paradygmatie wiadomości), ale nie są awizurami .NET wokół nich nie są. Aby zapobiec niespójnemu państwu podczas pracy z interfejsu użytkownika, wszystkie klasy Winforms mają specjalne kontrole, aby uzyskać dostęp do nich z różnych wątków.

Aby podsumować, podczas uzyskiwania dostępu do klas Winforms z różnych wątków nie ma domyślnego wyboru, istnieje tylko prosty kontrolny wątków, i dlatego powinieneś roztrzasłować samodzielnie.

1
arbiter 15 luty 2017, 14:02

Sta stoi dla Apartamenty pojedynczych gwintowanych Służy do upewnienia się, że jeden wątek może uzyskać dostęp do komponentu COM na raz. Wyjątek, który otrzymujesz, nie jest z powodu synchronizacji COM z wieloma wątkami, ale uzyskaj dostęp do kontroli w wątku, na którym nie jest utworzony.

Kontrola etykiety jest tworzona w wątku GUI i należy mieć dostęp do wątku, który jest utworzony I.e gwint gui. Próbujesz uzyskać dostęp do nim na wątku Non Gui, dlatego otrzymujesz wyjątek do wątku. Metoda Invoke będzie uzyskać dostęp do etykiety na wątku GUI, a nie otrzymasz wyjątku do wątku.

Komentarz OP

W tym przykładzie - Sta znajduje się z każdym połączeniem do składnika interfejsu użytkownika z innego wątku na wątek UI, więc jest faktycznie wykonywany na nitce UI i dlatego nie ma już żadnego wątku krzyżowego. Lub ma pracę w inny sposób?

Marshaling jest mechanizmem, przez który obiekt, który jest dostępny dla jednego mieszkania, może być udostępniany do innego mieszkania, Reference. Na komponentach COM, gdy wywołasz metodę wywołania wykonawczym jest apartament, a wyniki są zwracane do inicjatora połączenia. Z drugiej strony dla komponentów nie COM mieszkanie Sta nie przyjdzie w działaniu. Ograniczenie dostępu do obiektów GUI na wątku, które są tworzone, które są nałożone przez

Racholongowanie Ponieważ zasady obiektów modelu mieszkania jest to, że można je uzyskać tylko z wątku, na którym zostały utworzone, musisz wykonać dodatkową pracę, jeśli chcesz uzyskać dostęp do nich z innego wątku: musisz Wynajmuj Lackey. Com dzwoni do tego klawisza "proxy". Po wywołaniu metody na obiekcie proxy połączenie jest poprowadzone z powrotem do mieszkania pochodzącego, metoda wykonuje w swoim oryginalnym mieszkaniu, a następnie wyniki są prowadzone z powrotem do oryginalnego rozmówcy. (A jeśli którykolwiek z parametrów do metody są obiektami, a następnie COM musi tworzyć serwery proxy dla tych obiektów!) Rękowala jest mechanizmem tworzenia serwerów proxy.

Stathreadattribute.

Modele gwintowania COM dotyczą tylko aplikacji, które używają COM Interop. Model gwintowania COM można ustawić na apartament o pojedynczej gwintowanej lub wielowartościowym mieszkaniu. Wątek aplikacji jest zainicjowany tylko dla COM Interop, jeśli wątek faktycznie nawiązuje połączenie z komponentem COM. Jeśli COM Interop nie jest używany, gwint nie jest inicjowany, a atrybut stathreadattribute, jeśli jest obecny, nie ma efektu.

Jak: Wykonaj połączenia z plikiem Windows

Dostęp do sterowania formularzy Windows nie jest z natury bezpieczny. Jeśli masz dwa lub więcej wątków manipulowanie stanem kontroli, możliwe jest wymuszenie kontroli w niespójny stan. Możliwe są inne błędy związane z wątkami, takie jak warunki wyścigu i zakleszczenia. Ważne jest, aby upewnić się, że dostęp do kontrolek jest wykonywany w bezpieczny sposób. Jest to niebezpieczne, aby wywołać kontrolę z wątku innego niż ten, który utworzył sterowanie bez użycia metody wywołania. Poniżej znajduje się przykład połączenia, który nie jest bezpieczny.

3
Adil 16 luty 2017, 12:32