myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns
» Datenschutzerklärung
» Impressum

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » Gibt es die Möglichkeit den Ui Thread als MTA laufen zu lassen?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Gibt es die Möglichkeit den Ui Thread als MTA laufen zu lassen?

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8


D1990 ist offline

Gibt es die Möglichkeit den Ui Thread als MTA laufen zu lassen?

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Zusammen !

Ich lese schon seit längerer Zeit mal in diesem Forum nach wenn ich Probleme in der C# Programmierung habe, leider bin ich diesmal auf ein Problem gestoßen das ich durch das Nutzen von Suchfunktionen und Google nicht lösen konnte.

Derzeit arbeite ich an einem Projekt mit der Siemens API TIA Openness. Dabei schreibe ich an einer WPF- Anwendung welche ich nach dem MVVM Design Pattern strukturiert habe.

Im MainViewModel meines Codes wird anhand eines OpenFileDialogs eine Projektdatei gesucht welche dann ein Objekt des Typs TiaPortal instantiiert. Dies geschieht ganz normal im GUI-Thread.
Im weitereren Verlauf des Programms nutze ich dann einen async Task der das beschriebene Objekt aus eine anderen Thread bearbeitet damit während der langen Laufzeit die GUI nicht einfriert. Wenn währendessen Änderungen an GUI Elementen durchgeführt werden mussten, löste ich dies mittels der Dispatcher.Invoke Methode.

Dies funktionierte gut bis eine neue Version der .DLL veröffentlicht wurde:

Fehlermeldung:
Exception : Cross-thread operation is not valid in Openness within STA.

Nach einer langen Suche über STA und MTA im Kontext WPF kam ich dann
zum Entschluss mich in diesem Forum anzumelden um diesen Beitrag zu schreiben:

Gibt es die Möglichkeit den Ui Thread als MTA laufen zu lassen, bzw einen Workaround?
Leider kam ich noch zu keinem vernünfigten Ergebniss.


In der .DLL Dokumentation fand ich folgenden Text:

Zitat:
Thread-übergreifender Betrieb
Der Zugriff auf Openness-Objekte ist nicht inhärent threadsicher.
Wenn Sie Multithreading zur Verbesserung der Performance Ihrer Openness-Anwendung
einsetzen, wird die Erstellung der Instanz des TIA Portals mit MTA empfohlen.
Wenn TIA Portal innerhalb eines STA-Thread erstellt oder angehängt wird, sollte auf alle
Openness-Objekte in Zusammenhang mit dieser Instanz des TIA Portals aus demselben STAThread
zugegriffen werden; andernfalls wird eine Ausnahme ausgelöst.

Selbstverständlich könnte ich jetzt wieder die Bearbeitung im Main-thread(STA) durchführen was aber gleichzeitg das Einfrieren meiner Anwendung bedeuten würde.

Da ich ein kompletter Newbie im Bereich des Multithreadings bin bitte ich euch Tipps bzw. Anregungen wie ich das beschriebene Problem lösen könnte.

Beste Grüße und vielen Dank im Vorraus !
16.01.2019 16:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
witte
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 813


witte ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
fehlerhafte threadübergreifende Vorgänge erzeugen mitunter ein undefiniertes Verhalten, d.h. es wird nicht immer erkannt dass ein unzulässiger Zugriff durchgeführt wird. Es könnte also auch sein dass Du das schon immer fehlerhaft aufgerufen hast und die neue LibVersion das jetzt aber bemerkt und anmeckert.
16.01.2019 16:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Vielen Dank für deine Antwort Witte,

Leider finde ich nur Informationen die mir zeigen wie ich auf ein Control das dem UI-Thread gehört zugreifen kann, aber nicht wie auf ein Objekt.
Ich habe mir heute zum zweiten mal ein Kapitel zum Thema Threading(Rheinwerk Openbooks) durchgelesen und komme immernoch nicht weiter.

Ich teile deine Vermutung das schon vorher etwas falsch war, was nahe liegt da ich ein Anfänger in der ganzen C# Materie bin. Deshlab mal vereinfacht mein Code:

C#-Code:
public class myclass
{
     public myclass()
     {

      object= null;


     }
     private APIObject _object;
     public APIObject object(get.....

     private void mycommand_executed(object sender, EventArgs e)
     {

        if(object==null)
           {
            object = new APIObject();
           }
      }

    private aysnc void secondcommand_executed(object sender, EventArgs e)
   {
    //Hier passiert anderes zeug

   await Task.Run(() => Configuration);

   }

    private async Task Configuration()
   {
            if(object==null)
           {
            object = new APIObject() ;
           }
     //Hier kommen laufzeitintensive Methodenaufrufe des API Objekts
           object.DoSomething();
   }

}

Im Funktionsablauf meines Programms kann es also vorkommen das der Konstruktor des Objektes schon vor dem Starten des Task ausgeführt wird und somit das Objekt dem UI-Thread gehört (Wenn ich das richtig verstanden habe).

Ich hoffe das mir jemand weiterhelfen kann und das ganze nur ein blöder Anfängerfehler ist :-)

Viele Grüße und Danke

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von D1990 am 17.01.2019 13:23.

17.01.2019 12:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.785
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich kann mir nicht vorstellen, dass in dem Buch wirklich mit dem Typ object gearbeitet wird - also quasi untypisiert.

Vermutlich stimmt die gesamte Struktur nicht, denn man greift i.d.R. nicht auf irgendein Control zu - man bindet Informationen.
Sieht für mich jetzt nicht so aus, dass die Basis der Struktur korrekt ist.

Zitat:
Leider finde ich nur Informationen dei mir zeigen wie ich auf ein Control das dem UI-Thread gehört zugreifen kann, aber nicht wie auf ein Objekt.

Man greift auch nicht auf ein "Objekt" zu.
Das Objekt selbst liefert Events, auf die man lauscht - nicht umgekehrt.
17.01.2019 13:01 Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Abt !

Bitte verzeih mir, selbstverständlich habe ich nicht mit dem Typ

C#-Code:
object

gearbeit. Sollte nur ein Platzhalter für einen bestimmten Typ sein um es alllgemein zu halten. Ich gebe zu dass das nicht gerade geschickt gewählt war :-).

Bitte übergeh auch meine Äußerung zu den Controlls, da es nicht den Kernpunkt meiner Frage darstellt.


Beste Grüße !

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von D1990 am 17.01.2019 13:27.

17.01.2019 13:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 12.785
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Es ist keine besonders gute Idee Code zu zeigen, den Du verfälscht hast, um es "allgemein" zu halten... das bringt oft eher Probleme, wie in diesem Fall.
Zeig den wahren Code. Zur Not nenn die Klassen um, aber verfälsche es bitte nicht.
17.01.2019 13:46 Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich hoffe das es so besser zu verstehen ist. Die Exception kommt dann wenn vor
dem StartConfigurationCommand der OpenTIACommand genutzt wurde.

C#-Code:
namespace TIA.ViewModels
{
    class MainWindowViewModel : ViewModelBaseClass
    {
        public MainWindowViewModel()
        {
            _Tia = null;
            _Project=null;
            _Projects=null;
            StartConfigurationCommand = new  CommandBase(StartConfigurationCommand_Executed);
            OpenTiaCommand = new CommandBase(OpenTiaCommand_Executed);
        }

        private  TiaPortal _Tia;
        private  TiaProject _Project;
        private ProjectComposition _Projects;
        public CommandBase StartConfigurationCommand { get; set; }
        public CommandBase OpenTiaCommand { get; set; }

        private void OpenTiaCommand_Executed(object sender, EventArgs e)
        {
            if(_Tia==null)
            {
                _Tia= new TiaPortal();
                _Projects=_Tia.Projects;
                _Project=_Projects.Open("Pfad");
            }
        }


        private async void StartConfigurationCommand_Executed(object sender, EventArgs e)
        {
            try
            {
                await Task.Run(() => Configuration());
            }
            catch (Exception u)
            {
                System.Windows.MessageBox.Show(u.Message, "Error");
            }

        }

        private async Task Configuration()
        {
            if(_Tia==null)
            {
                _Tia= new TiaPortal();
                _Projects=_Tia.Projects;
                _Project=_Projects.Open("Pfad");
            }
            //HIER ENTSTEHT DIE EXCEPTION
            ProjectLibrary _projectLibrary = _Project.ProjectLibrary;


        }

    }
}
17.01.2019 16:00 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
witte
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 813


witte ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von D1990:
Die Exception kommt dann wenn vor
dem StartConfigurationCommand der OpenTIACommand genutzt wurde.

Überlappen sich beide zeitlich? Kommt der Fehler auch wenn die Befehle synchron ausgeführt werden? Möglicherweise greifen beide Methoden auf dieselben Objekte zu und müssen voneinander geschützt werden (SemaphoreSlim o.ä.)
17.01.2019 16:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Die Commands sollten sich nicht überlappen, da ich die Nutzung der Commands (CanExecute) je nach Situation unterbinde.
Deine zweite Frage verstehe ich nicht ganz. Nach meinem Verständnis rufe ich in der
asynchronen StartConfiguration durch Task.Run eine zweiten Thread auf der seine Arbeit wiederum synchron verarbeitet, da der await-Operator fehlt.
Wahrscheinlich wäre es besser wenn ich aus "async Task Configuration" einfach ein "void Configuration" mache.
Benutzte ich keinen Task.Run läuft der Code zwar durch, aber meine UI friert wieder ein.
18.01.2019 08:07 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
ThomasE. ThomasE. ist männlich
myCSharp.de-Mitglied

avatar-178.gif


Dabei seit: 26.11.2013
Beiträge: 427
Entwicklungsumgebung: Visual Studio 2015Pro/2017Ent


ThomasE. ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

auf Grund des Fehlers könnte man annehmen, daß bei

C#-Code:
        private void OpenTiaCommand_Executed(object sender, EventArgs e)
        {
            if(_Tia==null)
            {
                _Tia= new TiaPortal();
                _Projects=_Tia.Projects;
                _Project=_Projects.Open("Pfad");
            }
        }

das _Project längere Zeit in Verwendung ist und darauf zugegriffen wird, auch dann wenn

C#-Code:
        private async Task Configuration()
        {
            if(_Tia==null)
            {
                _Tia= new TiaPortal();
                _Projects=_Tia.Projects;
                _Project=_Projects.Open("Pfad");
            }
            //HIER ENTSTEHT DIE EXCEPTION
            ProjectLibrary _projectLibrary = _Project.ProjectLibrary;


        }

ausgeführt wird.

Also müßte man es kontrollieren, daß wenn er bei private async Task Configuration() ankommt, das _Project=_Projects.Open("Pfad"); bei private void OpenTiaCommand_Executed(object sender, EventArgs e) noch in Arbeit ist.

Grüße
18.01.2019 09:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Thomas, vielen Dank für deine Antwort !
Kannst du mir eine Tipp wie ich das am besten bewerkstelligen kann ?
Mein erster Verdacht wäre die Klasse Monitor zu nutzen, jedoch wüsste ich nicht wo ich dort am besten ansetzen würde.

Grüße !
18.01.2019 10:07 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Thread-übergreifender Betrieb
Der Zugriff auf Openness-Objekte ist nicht inhärent threadsicher.
Wenn Sie Multithreading zur Verbesserung der Performance Ihrer Openness-Anwendung
einsetzen, wird die Erstellung der Instanz des TIA Portals mit MTA empfohlen.
Wenn TIA Portal innerhalb eines STA-Thread erstellt oder angehängt wird, sollte auf alle
Openness-Objekte in Zusammenhang mit dieser Instanz des TIA Portals aus demselben STAThread
zugegriffen werden; andernfalls wird eine Ausnahme ausgelöst.

Da meines Wissens WPF Anwendungen immer in einem Single Thread Apartment gestartet werden, werde ich wohl einen anderen Weg finden müssen.
Gibt es die Möglichkeit alle Funktionen meiner Commands in einem Multi-Thread-Aparment ablaufen zu lassen ?
Oder alternativ meine UI über einen anderen Thread zu aktualisieren/ am Leben zu halten ?
18.01.2019 11:22 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
D1990
myCSharp.de-Mitglied

Dabei seit: 16.01.2019
Beiträge: 8

Themenstarter Thema begonnen von D1990

D1990 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Da meines Wissens WPF Anwendungen immer in einem Single Thread Apartment gestartet werden, werde ich wohl einen anderen Weg finden müssen.
Gibt es die Möglichkeit alle Funktionen meiner Commands in einem Multi-Thread-Aparment ablaufen zu lassen ?

Ok gut, Problem gelöst. Ich erstelle mein TIA Objekt nun in einem Task(MTA), das hat zu folge das ich es auch aus einem anderen Thread aufrufen kann. Demnach muss ich wohl zukünftig wesentlich mehr mit der ganzen Thematik auseiandersetzen, gerade im Bezug Threadsicherheit.
Ich werde mich dann nochmal in die Theorie stürzen :-)

Danke vielmals für die Tipps und Anregungen.
18.01.2019 12:29 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 6 Monate.
Der letzte Beitrag ist älter als 5 Monate.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 16.07.2019 08:00