WebBrowser uruchomiony w oddzielnym wątku wiesza go.

WebBrowser uruchomiony w oddzielnym wątku wiesza go.
Pixello
  • Rejestracja:około 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Podkarpacie
  • Postów:448
0

Witam,
Mam pewnien problem. Robię aplikację, gdzie muszę mieć serwer razem z gui w jednej aplikacji (tak sobie wymyślili...), i przez to mam Forma z aspNetem.
W przekazywaniu danych itp nie mam problemów, invokuje delegaty.
Problem mam gdy tam chcę wrzucić (2. wątek)webFormsa lub FlashPlayera z obiektów COM. Wyrzuca wyjątek podczas inicjalizacji, że dostęp z innego forma(tworzę go na pewno w tym samym wątku, chyba że on sam w sobie jakieś śmieszne rzeczy robi).

Macie jakieś pomysły jak można to rozwiązać?

Kod

Kopiuj
 
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Net;
using System.Threading;
using System.Windows.Forms;

namespace TWIN_API.Server_GUI.Presentation
{

    public class MainForm : Form //must be Singleton
    {

        internal System.Windows.Forms.Timer DelegateHandler;
        private System.ComponentModel.IContainer components;
        internal PictureBox pictureBox1;
        internal ProgressBar progressBar1;
        private WebBrowser webBrowser1;
        internal Label TextShower;
       


        public void ChangeProgress(int id)
        {
           this.progressBar1.Value = id;
        }

        public void Visiblity(Control control)
        {
            TextShower.Visible = false;
            pictureBox1.Visible = false;
            control.Visible = true;
        }


        public MainForm()
        {
            InitializeComponent();
        }


        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.DelegateHandler = new System.Windows.Forms.Timer(this.components);
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.TextShower = new System.Windows.Forms.Label();
            this.webBrowser1 = new System.Windows.Forms.WebBrowser();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureBox1
            // 
            this.pictureBox1.Location = new System.Drawing.Point(12, 12);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(300, 300);
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            // 
            // progressBar1
            // 
            this.progressBar1.Dock = System.Windows.Forms.DockStyle.Top;
            this.progressBar1.Location = new System.Drawing.Point(0, 0);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(643, 10);
            this.progressBar1.TabIndex = 2;
            // 
            // TextShower
            // 
            this.TextShower.AccessibleDescription = "TextShower";
            this.TextShower.AccessibleName = "TextShower";
            this.TextShower.Location = new System.Drawing.Point(9, 26);
            this.TextShower.Name = "TextShower";
            this.TextShower.Size = new System.Drawing.Size(300, 300);
            this.TextShower.TabIndex = 3;
            this.TextShower.Text = "TextShower";
            this.TextShower.Click += new System.EventHandler(this.TextShower_Click);
            // 
            // webBrowser1
            // 
            this.webBrowser1.Location = new System.Drawing.Point(160, 399);
            this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20);
            this.webBrowser1.Name = "webBrowser1";
            this.webBrowser1.Size = new System.Drawing.Size(250, 250);
            this.webBrowser1.TabIndex = 4;
            this.webBrowser1.Url = new System.Uri("https://www.youtube.com/v/qgeaoW55Pks", System.UriKind.Absolute);
            // 
            // MainForm
            // 
            this.ClientSize = new System.Drawing.Size(643, 733);
            this.ControlBox = false;
            this.Controls.Add(this.webBrowser1);
            this.Controls.Add(this.TextShower);
            this.Controls.Add(this.pictureBox1);
            this.Controls.Add(this.progressBar1);
            this.Name = "MainForm";
            this.Load += new System.EventHandler(this.MainForm_Load);
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);

        }


        private void button1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }

        private void axShockwaveFlash2_Enter(object sender, EventArgs e)
        {

        }

        private void TextShower_Click(object sender, EventArgs e)
        {

        }
    }

Kontroler ;

Kopiuj
 
  public class GuiController
    {
        protected static GuiController GuiControllerInstance {get; private set; }

        protected Task Task;

        public static GuiController GetGuiController()
        {
                return GuiControllerInstance;
        }

        public static bool TryStartGui()
        {
            if (GuiControllerInstance != null)
                return false;
            GuiControllerInstance = new GuiController();
            return true;
        }

       public delegate void GuiDoIt(MainForm form);

        
        virtual public void GuiInvoke(GuiDoIt GuiInvoker)
        {
            HandlerMainForm.Invoke(GuiInvoker, HandlerMainForm);
        }

        protected MainForm HandlerMainForm;
        protected void FormLoop()
        {
            Application.Run(HandlerMainForm);
        }

        public void Start()
        {
            Task = Task.Factory.StartNew(FormLoop);
        }

        /// <summary>
        /// Stop the task  NOTE!! Use Dispose instead at this implementation
        /// </summary>
        public virtual void Stop()
        {
            throw new NotSupportedException();
        }
        /// <summary>
        /// It end task asap
        /// </summary>
        public void Dispose()
        {
            Task.Dispose();
        }

        internal GuiController()
        {
            HandlerMainForm = new MainForm();
            Start();
        }
    }

Uruchamianie

Kopiuj
GuiController.TryStartGui();            

Bez tych toolsów wszystko działa, jak właduję albo WebBrowsera albo Flasha to się psuje.
Gdy tworzę forma w głównym wątku "Application.Run(new MainForm());", to działa.

edytowany 1x, ostatnio: Pixello
AreQrm
"serwer razem z gui w jednej aplikacji" to czemu nie zwykła aplikacji w WPF/WinForms tylko mieszanie ASP i WinForms? Rozumiem że np strona odpalana przez browser do zarządzania "serwerem" nie może być traktowana jako GUI i w "zwykłym" MVC tego nie możesz napisać? Czemu nie zrobisz ewentualnie normalnie desktopowej aplikacji łączącej się z np Web Api 2? Było by w sumie można później drugie gui dorobić webowe wtedy.
Pixello
Chodzi o soft do tablicy led, na kompie na którym to jest odpalane będzie uruchomiona aplikacja do zarządzania nią, wysyła część ekranu na której jest formularz. Przez api przeglądarki jest sterowane co ma być wyświetlone, razem z zwykłymi programami typu skype itp. GUI jest bardziej do prezentowania wyniku, serwer jest tylko do odbioru zapytań, które kontrolują tym co jest wyświetlane w gui. Apka mobilna też do tego wchodzi,ale to nie moja działka - ja mam wystawić api.
Pixello
  • Rejestracja:około 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Podkarpacie
  • Postów:448
0

Czyli co, ma ktoś jakiś pomysł, żeby to ogarnąć? Teraz nie mam jakiegoś przestoju bo inne moduły robię, ale za tego youtube wypadałoby się zabrać - z tego co czytałem na SO wszyscy odsyłają do filmików/Tematów gdzie polecają do formsów wrzucić jakiegoś webBrowsera/SFP. Pewnie jak nikt nie podrzuci pomysłu rozłożę to na 2 programy które będą startować jednocześnie, i komunikacja między nimi.

MC
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 8 lat
  • Lokalizacja:Wrocław
  • Postów:127
0

Obiekty COM muszą być uruchomione na wątku, który jest oznaczony jako STAThread. Cytacik: "STAThreadAttribute indicates that the COM threading model for the application is single-threaded apartment. This attribute must be present on the entry point of any application that uses Windows Forms; if it is omitted, the Windows components might not work correctly. If the attribute is not present, the application uses the multithreaded apartment model, which is not supported for Windows Forms."

Domyślna klasa Program.cs wygląda o tak:

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

Jak widzisz masz atrybut STAThread dlatego działa właśnie na tym wątku i nie działa na innym. Pozdrawiam.

Pixello
  • Rejestracja:około 10 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Podkarpacie
  • Postów:448
0

Tak, doszedłem do tego, ale sam [STAThread] wiele w mojej aplikacji nie dawał, trzeba było ustawić ten 2. thread

Kopiuj
t.SetApartmentState(ApartmentState.STA);

ale to nie pomogło, bo zaczęły się jakieś dziwne wyjątki sypać powiązane z obsługą activex.

Ogólnie przewertowałem trochę SO, kilka ludzi miało podobny problem, ale z każdym rozwiązaniem był jakiś problem u mnie.

edytowany 2x, ostatnio: Pixello

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.